yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
project_commands.cc
Go to the documentation of this file.
2
3#include <filesystem>
4#include <iostream>
5
6#include "core/asar_wrapper.h"
7#include "core/project.h"
8#include "util/bps.h"
9#include "util/file_util.h"
10#include "util/macro.h"
11
12namespace yaze {
13namespace cli {
14namespace handlers {
15
17 Rom* rom, const resources::ArgumentParser& parser,
18 resources::OutputFormatter& formatter) {
19 auto project_opt = parser.GetString("project_name");
20
21 if (!project_opt.has_value()) {
22 return absl::InvalidArgumentError(
23 "Missing required argument: project_name");
24 }
25
26 std::string project_name = project_opt.value();
27
29 auto status = project.Create(project_name, ".");
30 if (!status.ok()) {
31 return status;
32 }
33
34 formatter.AddField("status", "success");
35 formatter.AddField("message",
36 "Successfully initialized project: " + project_name);
37 formatter.AddField("project_name", project_name);
38
39 return absl::OkStatus();
40}
41
43 Rom* rom, const resources::ArgumentParser& parser,
44 resources::OutputFormatter& formatter) {
46 auto status = project.Open(".");
47 if (!status.ok()) {
48 return status;
49 }
50
51 Rom build_rom;
52 status = build_rom.LoadFromFile(project.rom_filename);
53 if (!status.ok()) {
54 return status;
55 }
56
57 // Apply BPS patches - cross-platform with std::filesystem
58 namespace fs = std::filesystem;
59 std::vector<std::string> bps_files;
60
61 try {
62 for (const auto& entry : fs::directory_iterator(project.patches_folder)) {
63 if (entry.path().extension() == ".bps") {
64 bps_files.push_back(entry.path().string());
65 }
66 }
67 } catch (const fs::filesystem_error& e) {
68 // Patches folder doesn't exist or not accessible
69 }
70
71 for (const auto& patch_file : bps_files) {
72 std::vector<uint8_t> patch_data;
73 auto patch_contents = util::LoadFile(patch_file);
74 std::copy(patch_contents.begin(), patch_contents.end(),
75 std::back_inserter(patch_data));
76 std::vector<uint8_t> patched_rom;
77 util::ApplyBpsPatch(build_rom.vector(), patch_data, patched_rom);
78 build_rom.LoadFromData(patched_rom);
79 }
80
81 // Run asar on assembly files - cross-platform
82 std::vector<std::string> asm_files;
83 try {
84 for (const auto& entry : fs::directory_iterator(project.patches_folder)) {
85 if (entry.path().extension() == ".asm") {
86 asm_files.push_back(entry.path().string());
87 }
88 }
89 } catch (const fs::filesystem_error& e) {
90 // No asm files
91 }
92
93 // Apply ASM patches using Asar
94 if (!asm_files.empty()) {
96 auto init_status = asar.Initialize();
97 if (!init_status.ok()) {
98 formatter.AddField("warning",
99 "Asar not available, skipping ASM patches: " +
100 std::string(init_status.message()));
101 } else {
102 for (const auto& asm_file : asm_files) {
103 auto rom_data = build_rom.vector();
104 auto result = asar.ApplyPatch(asm_file, rom_data);
105
106 if (!result.ok()) {
107 return absl::InternalError(
108 "ASM patch failed for " + asm_file + ": " +
109 std::string(result.status().message()));
110 }
111
112 if (result->success) {
113 build_rom.LoadFromData(rom_data);
114 formatter.AddField("asm_applied", asm_file);
115
116 // Log extracted symbols count
117 if (!result->symbols.empty()) {
118 formatter.AddField(
119 "symbols_" + fs::path(asm_file).stem().string(),
120 std::to_string(result->symbols.size()) + " symbols");
121 }
122 } else {
123 // Log errors but continue with other patches
124 std::string error_msg = "Errors in " + asm_file + ":";
125 for (const auto& error : result->errors) {
126 error_msg += "\n " + error;
127 }
128 formatter.AddField("error", error_msg);
129 return absl::InternalError(error_msg);
130 }
131 }
132 }
133 }
134
135 std::string output_file = project.name + ".sfc";
136 status = build_rom.SaveToFile({.save_new = true, .filename = output_file});
137 if (!status.ok()) {
138 return status;
139 }
140
141 formatter.AddField("status", "success");
142 formatter.AddField("message", "Successfully built project: " + project.name);
143 formatter.AddField("project_name", project.name);
144 formatter.AddField("output_file", output_file);
145
146 return absl::OkStatus();
147}
148
149} // namespace handlers
150} // namespace cli
151} // 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
absl::Status SaveToFile(const SaveSettings &settings)
Definition rom.cc:164
absl::Status LoadFromData(const std::vector< uint8_t > &data, const LoadOptions &options=LoadOptions::Defaults())
Definition rom.cc:147
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.
Modern C++ wrapper for Asar 65816 assembler integration.
absl::StatusOr< AsarPatchResult > ApplyPatch(const std::string &patch_path, std::vector< uint8_t > &rom_data, const std::vector< std::string > &include_paths={})
absl::Status Initialize()
absl::Status ApplyBpsPatch(const std::vector< uint8_t > &source, const std::vector< uint8_t > &patch, std::vector< uint8_t > &output)
Definition bps.cc:79
std::string LoadFile(const std::string &filename)
Loads the entire contents of a file into a string.
Definition file_util.cc:23
Modern project structure with comprehensive settings consolidation.
Definition project.h:84
std::string rom_filename
Definition project.h:92
std::string patches_folder
Definition project.h:99
absl::Status Create(const std::string &project_name, const std::string &base_path)
Definition project.cc:99
absl::Status Open(const std::string &project_path)
Definition project.cc:151