47 auto status = project.
Open(
".");
59 namespace fs = std::filesystem;
60 std::vector<std::string> bps_files;
63 for (
const auto& entry : fs::directory_iterator(project.
patches_folder)) {
64 if (entry.path().extension() ==
".bps") {
65 bps_files.push_back(entry.path().string());
68 }
catch (
const fs::filesystem_error& e) {
72 for (
const auto& patch_file : bps_files) {
73 std::ifstream patch_stream(patch_file, std::ios::binary);
74 if (!patch_stream.is_open()) {
75 return absl::InternalError(
"Failed to open BPS patch: " + patch_file);
78 std::vector<uint8_t> patch_data(
79 (std::istreambuf_iterator<char>(patch_stream)),
80 std::istreambuf_iterator<char>());
81 if (patch_data.empty()) {
82 return absl::InvalidArgumentError(
"BPS patch is empty: " + patch_file);
85 std::vector<uint8_t> patched_rom;
88 if (!apply_status.ok()) {
89 return absl::InternalError(
"Failed to apply BPS patch " + patch_file +
90 ": " + std::string(apply_status.message()));
93 auto load_patched_status = build_rom.
LoadFromData(patched_rom);
94 if (!load_patched_status.ok()) {
95 return absl::InternalError(
"Failed to load patched ROM after " +
97 std::string(load_patched_status.message()));
102 std::vector<std::string> asm_files;
104 for (
const auto& entry : fs::directory_iterator(project.
patches_folder)) {
105 if (entry.path().extension() ==
".asm") {
106 asm_files.push_back(entry.path().string());
109 }
catch (
const fs::filesystem_error& e) {
114 if (!asm_files.empty()) {
117 if (!init_status.ok()) {
119 "Asar not available, skipping ASM patches: " +
120 std::string(init_status.message()));
122 for (
const auto& asm_file : asm_files) {
123 auto rom_data = build_rom.
vector();
124 auto result = asar.
ApplyPatch(asm_file, rom_data);
127 return absl::InternalError(
"ASM patch failed for " + asm_file +
": " +
128 std::string(result.status().message()));
131 if (result->success) {
133 formatter.
AddField(
"asm_applied", asm_file);
136 if (!result->symbols.empty()) {
138 "symbols_" + fs::path(asm_file).stem().
string(),
139 std::to_string(result->symbols.size()) +
" symbols");
143 std::string error_msg =
"Errors in " + asm_file +
":";
144 for (
const auto& error : result->errors) {
145 error_msg +=
"\n " + error;
147 formatter.
AddField(
"error", error_msg);
148 return absl::InternalError(error_msg);
154 std::string output_file = project.
name +
".sfc";
155 status = build_rom.
SaveToFile({.save_new =
true, .filename = output_file});
160 formatter.
AddField(
"status",
"success");
161 formatter.
AddField(
"message",
"Successfully built project: " + project.
name);
163 formatter.
AddField(
"output_file", output_file);
165 return absl::OkStatus();