yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
rom_commands.cc
Go to the documentation of this file.
2
3#include <fstream>
4
5#include "absl/strings/str_format.h"
6#include "util/macro.h"
7
8namespace yaze {
9namespace cli {
10namespace handlers {
11
13 Rom* rom, const resources::ArgumentParser& parser,
14 resources::OutputFormatter& formatter) {
15 if (!rom || !rom->is_loaded()) {
16 return absl::FailedPreconditionError("ROM must be loaded");
17 }
18
19 formatter.AddField("title", rom->title());
20 formatter.AddField("size", absl::StrFormat("0x%X", rom->size()));
21 formatter.AddField("size_bytes", static_cast<int>(rom->size()));
22
23 return absl::OkStatus();
24}
25
27 Rom* rom, const resources::ArgumentParser& parser,
28 resources::OutputFormatter& formatter) {
29 if (!rom || !rom->is_loaded()) {
30 return absl::FailedPreconditionError("ROM must be loaded");
31 }
32
33 bool all_ok = true;
34 std::vector<std::string> validation_results;
35
36 // Basic ROM validation - check if ROM is loaded and has reasonable size
37 if (rom->is_loaded() && rom->size() > 0) {
38 validation_results.push_back("checksum: PASSED");
39 } else {
40 validation_results.push_back("checksum: FAILED");
41 all_ok = false;
42 }
43
44 // Header validation
45 if (rom->title() == "THE LEGEND OF ZELDA") {
46 validation_results.push_back("header: PASSED");
47 } else {
48 validation_results.push_back(
49 "header: FAILED (Invalid title: " + rom->title() + ")");
50 all_ok = false;
51 }
52
53 formatter.AddField("validation_passed", all_ok);
54 std::string results_str;
55 for (const auto& result : validation_results) {
56 if (!results_str.empty())
57 results_str += "; ";
58 results_str += result;
59 }
60 formatter.AddField("results", results_str);
61
62 return absl::OkStatus();
63}
64
66 Rom* rom, const resources::ArgumentParser& parser,
67 resources::OutputFormatter& formatter) {
68 auto rom_a_opt = parser.GetString("rom_a");
69 auto rom_b_opt = parser.GetString("rom_b");
70
71 if (!rom_a_opt.has_value()) {
72 return absl::InvalidArgumentError("Missing required argument: rom_a");
73 }
74 if (!rom_b_opt.has_value()) {
75 return absl::InvalidArgumentError("Missing required argument: rom_b");
76 }
77
78 std::string rom_a_path = rom_a_opt.value();
79 std::string rom_b_path = rom_b_opt.value();
80
81 Rom rom_a;
82 auto status_a = rom_a.LoadFromFile(rom_a_path);
83 if (!status_a.ok()) {
84 return status_a;
85 }
86
87 Rom rom_b;
88 auto status_b = rom_b.LoadFromFile(rom_b_path);
89 if (!status_b.ok()) {
90 return status_b;
91 }
92
93 if (rom_a.size() != rom_b.size()) {
94 formatter.AddField("size_match", false);
95 formatter.AddField("size_a", static_cast<int>(rom_a.size()));
96 formatter.AddField("size_b", static_cast<int>(rom_b.size()));
97 return absl::OkStatus();
98 }
99
100 int differences = 0;
101 std::vector<std::string> diff_details;
102
103 for (size_t i = 0; i < rom_a.size(); ++i) {
104 if (rom_a.vector()[i] != rom_b.vector()[i]) {
105 differences++;
106 if (differences <= 10) { // Limit output to first 10 differences
107 diff_details.push_back(absl::StrFormat("0x%08X: 0x%02X vs 0x%02X", i,
108 rom_a.vector()[i],
109 rom_b.vector()[i]));
110 }
111 }
112 }
113
114 formatter.AddField("identical", differences == 0);
115 formatter.AddField("differences_count", differences);
116 if (!diff_details.empty()) {
117 std::string diff_str;
118 for (const auto& diff : diff_details) {
119 if (!diff_str.empty())
120 diff_str += "; ";
121 diff_str += diff;
122 }
123 formatter.AddField("differences", diff_str);
124 }
125
126 return absl::OkStatus();
127}
128
130 Rom* rom, const resources::ArgumentParser& parser,
131 resources::OutputFormatter& formatter) {
132 auto rom_opt = parser.GetString("rom_file");
133 auto golden_opt = parser.GetString("golden_file");
134
135 if (!rom_opt.has_value()) {
136 return absl::InvalidArgumentError("Missing required argument: rom_file");
137 }
138 if (!golden_opt.has_value()) {
139 return absl::InvalidArgumentError("Missing required argument: golden_file");
140 }
141
142 std::string rom_path = rom_opt.value();
143 std::string golden_path = golden_opt.value();
144
145 Rom source_rom;
146 auto status = source_rom.LoadFromFile(rom_path);
147 if (!status.ok()) {
148 return status;
149 }
150
151 std::ofstream file(golden_path, std::ios::binary);
152 if (!file.is_open()) {
153 return absl::NotFoundError("Could not open file for writing: " +
154 golden_path);
155 }
156
157 file.write(reinterpret_cast<const char*>(source_rom.vector().data()),
158 source_rom.size());
159
160 formatter.AddField("status", "success");
161 formatter.AddField("golden_file", golden_path);
162 formatter.AddField("source_file", rom_path);
163 formatter.AddField("size", static_cast<int>(source_rom.size()));
164
165 return absl::OkStatus();
166}
167
168} // namespace handlers
169} // namespace cli
170} // namespace yaze
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
Definition rom.h:24
absl::Status LoadFromFile(const std::string &filename, const LoadOptions &options=LoadOptions::Defaults())
Definition rom.cc:74
const auto & vector() const
Definition rom.h:139
auto size() const
Definition rom.h:134
bool is_loaded() const
Definition rom.h:128
auto title() const
Definition rom.h:133
absl::Status Execute(Rom *rom, const resources::ArgumentParser &parser, resources::OutputFormatter &formatter) override
Execute the command business logic.
absl::Status Execute(Rom *rom, const resources::ArgumentParser &parser, resources::OutputFormatter &formatter) override
Execute the command business logic.
absl::Status Execute(Rom *rom, const resources::ArgumentParser &parser, resources::OutputFormatter &formatter) override
Execute the command business logic.
absl::Status Execute(Rom *rom, const resources::ArgumentParser &parser, resources::OutputFormatter &formatter) override
Execute the command business logic.
Utility for parsing common CLI argument patterns.
std::optional< std::string > GetString(const std::string &name) const
Parse a named argument (e.g., –format=json or –format json)
Utility for consistent output formatting across commands.
void AddField(const std::string &key, const std::string &value)
Add a key-value pair.