yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
asar_wrapper.cc
Go to the documentation of this file.
1#include "core/asar_wrapper.h"
2
3#include <filesystem>
4#include <fstream>
5#include <iostream>
6#include <sstream>
7
8#include "absl/strings/str_format.h"
9#include "absl/strings/str_join.h"
10
11// Include Asar C bindings
12#include "asar-dll-bindings/c/asar.h"
13
14namespace yaze {
15namespace core {
16
17AsarWrapper::AsarWrapper() : initialized_(false) {}
18
20 if (initialized_) {
21 Shutdown();
22 }
23}
24
26 if (initialized_) {
27 return absl::OkStatus();
28 }
29
30 // Verify API version compatibility
31 int api_version = asar_apiversion();
32 if (api_version < 300) { // Require at least API version 3.0
33 return absl::InternalError(absl::StrFormat(
34 "Asar API version %d is too old (required: 300+)", api_version));
35 }
36
37 initialized_ = true;
38 return absl::OkStatus();
39}
40
42 if (initialized_) {
43 // Note: Static library doesn't have asar_close()
44 initialized_ = false;
45 }
46}
47
48std::string AsarWrapper::GetVersion() const {
49 if (!initialized_) {
50 return "Not initialized";
51 }
52
53 int version = asar_version();
54 int major = version / 10000;
55 int minor = (version / 100) % 100;
56 int patch = version % 100;
57
58 return absl::StrFormat("%d.%d.%d", major, minor, patch);
59}
60
62 if (!initialized_) {
63 return 0;
64 }
65 return asar_apiversion();
66}
67
68absl::StatusOr<AsarPatchResult> AsarWrapper::ApplyPatch(
69 const std::string& patch_path,
70 std::vector<uint8_t>& rom_data,
71 const std::vector<std::string>& include_paths) {
72
73 if (!initialized_) {
74 return absl::FailedPreconditionError("Asar not initialized");
75 }
76
77 // Reset previous state
78 Reset();
79
80 AsarPatchResult result;
81 result.success = false;
82
83 // Prepare ROM data
84 int rom_size = static_cast<int>(rom_data.size());
85 int buffer_size = std::max(rom_size, 16 * 1024 * 1024); // At least 16MB buffer
86
87 // Resize ROM data if needed
88 if (rom_data.size() < static_cast<size_t>(buffer_size)) {
89 rom_data.resize(buffer_size, 0);
90 }
91
92 // Apply the patch
93 bool patch_success = asar_patch(
94 patch_path.c_str(),
95 reinterpret_cast<char*>(rom_data.data()),
96 buffer_size,
97 &rom_size);
98
99 // Process results
102
103 result.errors = last_errors_;
104 result.warnings = last_warnings_;
105 result.success = patch_success && last_errors_.empty();
106
107 if (result.success) {
108 // Resize ROM data to actual size
109 rom_data.resize(rom_size);
110 result.rom_size = rom_size;
111
112 // Extract symbols
114 result.symbols.reserve(symbol_table_.size());
115 for (const auto& [name, symbol] : symbol_table_) {
116 result.symbols.push_back(symbol);
117 }
118
119 // Calculate CRC32 if available
120 // Note: Asar might provide this, check if function exists
121 result.crc32 = 0; // TODO: Implement CRC32 calculation
122 } else {
123 return absl::InternalError(absl::StrFormat(
124 "Patch failed: %s", absl::StrJoin(last_errors_, "; ")));
125 }
126
127 return result;
128}
129
130absl::StatusOr<AsarPatchResult> AsarWrapper::ApplyPatchFromString(
131 const std::string& patch_content,
132 std::vector<uint8_t>& rom_data,
133 const std::string& base_path) {
134
135 if (!initialized_) {
136 return absl::FailedPreconditionError("Asar not initialized");
137 }
138
139 // Reset previous state
140 Reset();
141
142 // Write patch content to temporary file
143 std::filesystem::path temp_patch_path =
144 std::filesystem::temp_directory_path() / "yaze_asar_temp.asm";
145
146 std::ofstream temp_patch_file(temp_patch_path);
147 if (!temp_patch_file) {
148 return absl::InternalError("Failed to create temporary patch file");
149 }
150
151 temp_patch_file << patch_content;
152 temp_patch_file.close();
153
154 // Apply patch using temporary file
155 auto patch_result = ApplyPatch(temp_patch_path.string(), rom_data, {base_path});
156
157 // Clean up temporary file
158 std::error_code ec;
159 std::filesystem::remove(temp_patch_path, ec);
160
161 return patch_result;
162}
163
164absl::StatusOr<std::vector<AsarSymbol>> AsarWrapper::ExtractSymbols(
165 const std::string& asm_path,
166 const std::vector<std::string>& include_paths) {
167 if (!initialized_) {
168 return absl::FailedPreconditionError("Asar not initialized");
169 }
170
171 // Reset state before extraction
172 Reset();
173
174 // Create a dummy ROM for symbol extraction
175 std::vector<uint8_t> dummy_rom(1024 * 1024, 0); // 1MB dummy ROM
176
177 auto result = ApplyPatch(asm_path, dummy_rom, include_paths);
178 if (!result.ok()) {
179 return result.status();
180 }
181
182 return result->symbols;
183}
184
185std::map<std::string, AsarSymbol> AsarWrapper::GetSymbolTable() const {
186 return symbol_table_;
187}
188
189std::optional<AsarSymbol> AsarWrapper::FindSymbol(const std::string& name) const {
190 auto it = symbol_table_.find(name);
191 if (it != symbol_table_.end()) {
192 return it->second;
193 }
194 return std::nullopt;
195}
196
197std::vector<AsarSymbol> AsarWrapper::GetSymbolsAtAddress(uint32_t address) const {
198 std::vector<AsarSymbol> symbols;
199 for (const auto& [name, symbol] : symbol_table_) {
200 if (symbol.address == address) {
201 symbols.push_back(symbol);
202 }
203 }
204 return symbols;
205}
206
208 if (initialized_) {
209 asar_reset();
210 }
211 symbol_table_.clear();
212 last_errors_.clear();
213 last_warnings_.clear();
214}
215
217 const std::vector<uint8_t>& original_rom,
218 const std::vector<uint8_t>& modified_rom,
219 const std::string& patch_path) {
220
221 // This is a complex operation that would require:
222 // 1. Analyzing differences between ROMs
223 // 2. Generating appropriate assembly code
224 // 3. Writing the patch file
225
226 // For now, return not implemented
227 return absl::UnimplementedError(
228 "Patch creation from ROM differences not yet implemented");
229}
230
231absl::Status AsarWrapper::ValidateAssembly(const std::string& asm_path) {
232 // Create a dummy ROM for validation
233 std::vector<uint8_t> dummy_rom(1024, 0);
234
235 auto result = ApplyPatch(asm_path, dummy_rom);
236 if (!result.ok()) {
237 return result.status();
238 }
239
240 if (!result->success) {
241 return absl::InvalidArgumentError(absl::StrFormat(
242 "Assembly validation failed: %s",
243 absl::StrJoin(result->errors, "; ")));
244 }
245
246 return absl::OkStatus();
247}
248
250 last_errors_.clear();
251
252 int error_count = 0;
253 const errordata* errors = asar_geterrors(&error_count);
254
255 for (int i = 0; i < error_count; ++i) {
256 last_errors_.push_back(std::string(errors[i].fullerrdata));
257 }
258}
259
261 last_warnings_.clear();
262
263 int warning_count = 0;
264 const errordata* warnings = asar_getwarnings(&warning_count);
265
266 for (int i = 0; i < warning_count; ++i) {
267 last_warnings_.push_back(std::string(warnings[i].fullerrdata));
268 }
269}
270
272 symbol_table_.clear();
273
274 // Extract labels using the correct API function
275 int symbol_count = 0;
276 const labeldata* labels = asar_getalllabels(&symbol_count);
277
278 for (int i = 0; i < symbol_count; ++i) {
279 AsarSymbol symbol;
280 symbol.name = std::string(labels[i].name);
281 symbol.address = labels[i].location;
282 symbol.file = ""; // Not available in basic API
283 symbol.line = 0; // Not available in basic API
284 symbol.opcode = ""; // Would need additional processing
285 symbol.comment = "";
286
287 symbol_table_[symbol.name] = symbol;
288 }
289}
290
291AsarSymbol AsarWrapper::ConvertAsarSymbol(const void* asar_symbol_data) const {
292 // This would convert from Asar's internal symbol representation
293 // to our AsarSymbol struct. Implementation depends on Asar's API.
294
295 AsarSymbol symbol;
296 // Placeholder implementation
297 return symbol;
298}
299
300} // namespace core
301} // namespace yaze
absl::StatusOr< AsarPatchResult > ApplyPatchFromString(const std::string &patch_content, std::vector< uint8_t > &rom_data, const std::string &base_path="")
AsarSymbol ConvertAsarSymbol(const void *asar_symbol_data) const
absl::Status CreatePatch(const std::vector< uint8_t > &original_rom, const std::vector< uint8_t > &modified_rom, const std::string &patch_path)
std::vector< std::string > last_warnings_
absl::Status ValidateAssembly(const std::string &asm_path)
std::optional< AsarSymbol > FindSymbol(const std::string &name) const
std::string GetVersion() const
std::map< std::string, AsarSymbol > symbol_table_
absl::Status Initialize()
absl::StatusOr< AsarPatchResult > ApplyPatch(const std::string &patch_path, std::vector< uint8_t > &rom_data, const std::vector< std::string > &include_paths={})
std::vector< std::string > last_errors_
absl::StatusOr< std::vector< AsarSymbol > > ExtractSymbols(const std::string &asm_path, const std::vector< std::string > &include_paths={})
std::vector< AsarSymbol > GetSymbolsAtAddress(uint32_t address) const
std::map< std::string, AsarSymbol > GetSymbolTable() const
Main namespace for the application.
Definition controller.cc:20
Asar patch result information.
std::vector< std::string > errors
std::vector< AsarSymbol > symbols
std::vector< std::string > warnings
Symbol information extracted from Asar assembly.