yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
rom_file_manager.cc
Go to the documentation of this file.
1#include "rom_file_manager.h"
2
3#include <chrono>
4#include <filesystem>
5#include <fstream>
6
7#include "absl/strings/str_format.h"
9#include "rom/rom.h"
10#include "util/file_util.h"
11#include "zelda3/game_data.h"
12
13namespace yaze::editor {
14
16 : toast_manager_(toast_manager) {}
17
18absl::Status RomFileManager::LoadRom(Rom* rom, const std::string& filename) {
19 if (!rom) {
20 return absl::InvalidArgumentError("ROM pointer cannot be null");
21 }
22 if (filename.empty()) {
23 return absl::InvalidArgumentError("No filename provided");
24 }
25 return LoadRomFromFile(rom, filename);
26}
27
28absl::Status RomFileManager::SaveRom(Rom* rom) {
29 if (!IsRomLoaded(rom)) {
30 return absl::FailedPreconditionError("No ROM loaded to save");
31 }
32
33 Rom::SaveSettings settings;
34 settings.backup = true;
35 settings.save_new = false;
36 // settings.z3_save = true; // Deprecated: Handled by save callback or controller
37
38 auto status = rom->SaveToFile(settings);
39 if (!status.ok() && toast_manager_) {
41 absl::StrFormat("Failed to save ROM: %s", status.message()),
43 } else if (toast_manager_) {
44 toast_manager_->Show("ROM saved successfully", ToastType::kSuccess);
45 }
46 return status;
47}
48
49absl::Status RomFileManager::SaveRomAs(Rom* rom, const std::string& filename) {
50 if (!IsRomLoaded(rom)) {
51 return absl::FailedPreconditionError("No ROM loaded to save");
52 }
53 if (filename.empty()) {
54 return absl::InvalidArgumentError("No filename provided for save as");
55 }
56
57 Rom::SaveSettings settings;
58 settings.backup = false;
59 settings.save_new = true;
60 settings.filename = filename;
61 // settings.z3_save = true; // Deprecated
62
63 auto status = rom->SaveToFile(settings);
64 if (!status.ok() && toast_manager_) {
66 absl::StrFormat("Failed to save ROM as: %s", status.message()),
68 } else if (toast_manager_) {
69 toast_manager_->Show(absl::StrFormat("ROM saved as: %s", filename),
71 }
72 return status;
73}
74
76 const std::string& filename) {
77 if (!rom) {
78 return absl::InvalidArgumentError("ROM pointer cannot be null");
79 }
80 if (filename.empty()) {
81 return absl::InvalidArgumentError("No filename provided");
82 }
83
84 std::string extension = std::filesystem::path(filename).extension().string();
85
86 if (extension == ".yaze" || extension == ".json") {
87 return absl::UnimplementedError("Project file loading not yet implemented");
88 }
89
90 return LoadRom(rom, filename);
91}
92
94 if (!IsRomLoaded(rom)) {
95 return absl::FailedPreconditionError("No ROM loaded to backup");
96 }
97
98 std::string backup_filename = GenerateBackupFilename(rom->filename());
99
100 Rom::SaveSettings settings;
101 settings.backup = true;
102 settings.filename = backup_filename;
103 // settings.z3_save = true; // Deprecated
104
105 auto status = rom->SaveToFile(settings);
106 if (!status.ok() && toast_manager_) {
108 absl::StrFormat("Failed to create backup: %s", status.message()),
110 } else if (toast_manager_) {
111 toast_manager_->Show(absl::StrFormat("Backup created: %s", backup_filename),
113 }
114 return status;
115}
116
118 if (!IsRomLoaded(rom)) {
119 return absl::FailedPreconditionError("No valid ROM to validate");
120 }
121
122 if (rom->size() < 512 * 1024 || rom->size() > 8 * 1024 * 1024) {
123 return absl::InvalidArgumentError("ROM size is outside expected range");
124 }
125 if (rom->title().empty()) {
126 return absl::InvalidArgumentError("ROM title is empty or invalid");
127 }
128
129 if (toast_manager_) {
130 toast_manager_->Show("ROM validation passed", ToastType::kSuccess);
131 }
132 return absl::OkStatus();
133}
134
136 return rom && rom->is_loaded();
137}
138
139std::string RomFileManager::GetRomFilename(Rom* rom) const {
140 if (!IsRomLoaded(rom)) {
141 return "";
142 }
143 return rom->filename();
144}
145
147 const std::string& filename) {
148 if (!rom) {
149 return absl::InvalidArgumentError("ROM pointer cannot be null");
150 }
151 if (!IsValidRomFile(filename)) {
152 return absl::InvalidArgumentError(
153 absl::StrFormat("Invalid ROM file: %s", filename));
154 }
155
156 auto status = rom->LoadFromFile(filename);
157 if (!status.ok()) {
158 if (toast_manager_) {
160 absl::StrFormat("Failed to load ROM: %s", status.message()),
162 }
163 return status;
164 }
165
166 // IMPORTANT: Game data loading is now decoupled and should be handled
167 // by the caller (EditorManager) or a higher-level orchestration layer
168 // that manages both the generic Rom and the Zelda3::GameData.
169 // This class is strictly for generic ROM file operations.
170
171 if (toast_manager_) {
172 toast_manager_->Show(absl::StrFormat("ROM loaded: %s", rom->title()),
174 }
175 return absl::OkStatus();
176}
177
179 const std::string& original_filename) const {
180 std::filesystem::path path(original_filename);
181 std::string stem = path.stem().string();
182 std::string extension = path.extension().string();
183
184 auto now = std::chrono::system_clock::now();
185 auto time_t = std::chrono::system_clock::to_time_t(now);
186
187 return absl::StrFormat("%s_backup_%ld%s", stem, time_t, extension);
188}
189
190bool RomFileManager::IsValidRomFile(const std::string& filename) const {
191 if (filename.empty()) {
192 return false;
193 }
194
195 if (!std::filesystem::exists(filename)) {
196 return false;
197 }
198
199 auto file_size = std::filesystem::file_size(filename);
200 // Zelda 3 ROMs are 1MB (0x100000 = 1,048,576 bytes), possibly with 512-byte
201 // SMC header. Allow ROMs from 512KB to 8MB to be safe.
202 if (file_size < 512 * 1024 || file_size > 8 * 1024 * 1024) {
203 return false;
204 }
205
206 return true;
207}
208
209} // namespace yaze::editor
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
auto filename() const
Definition rom.h:141
absl::Status SaveToFile(const SaveSettings &settings)
Definition rom.cc:164
auto size() const
Definition rom.h:134
bool is_loaded() const
Definition rom.h:128
auto title() const
Definition rom.h:133
std::string GenerateBackupFilename(const std::string &original_filename) const
absl::Status OpenRomOrProject(Rom *rom, const std::string &filename)
absl::Status ValidateRom(Rom *rom)
RomFileManager(ToastManager *toast_manager)
std::string GetRomFilename(Rom *rom) const
absl::Status CreateBackup(Rom *rom)
absl::Status LoadRom(Rom *rom, const std::string &filename)
absl::Status SaveRom(Rom *rom)
absl::Status LoadRomFromFile(Rom *rom, const std::string &filename)
bool IsValidRomFile(const std::string &filename) const
absl::Status SaveRomAs(Rom *rom, const std::string &filename)
bool IsRomLoaded(Rom *rom) const
void Show(const std::string &message, ToastType type=ToastType::kInfo, float ttl_seconds=3.0f)
Editors are the view controllers for the application.
Definition agent_chat.cc:23
std::string filename
Definition rom.h:29