yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
rom_lifecycle_manager.cc
Go to the documentation of this file.
2
3#include <algorithm>
4#include <cctype>
5#include <string>
6#include <vector>
7
8#include "absl/status/status.h"
9#include "absl/strings/ascii.h"
10#include "absl/strings/match.h"
11#include "absl/strings/str_format.h"
15#include "core/hack_manifest.h"
16#include "core/project.h"
17#include "rom/rom.h"
18#include "util/rom_hash.h"
20
21namespace yaze::editor {
22
23namespace {
24
25std::string NormalizeHash(std::string value) {
26 absl::AsciiStrToLower(&value);
27 if (absl::StartsWith(value, "0x")) {
28 value = value.substr(2);
29 }
30 value.erase(std::remove_if(value.begin(), value.end(),
31 [](unsigned char c) { return std::isspace(c); }),
32 value.end());
33 return value;
34}
35
36} // namespace
37
39 : rom_file_manager_(deps.rom_file_manager),
40 session_coordinator_(deps.session_coordinator),
41 toast_manager_(deps.toast_manager),
42 popup_manager_(deps.popup_manager),
43 project_(deps.project) {}
44
52
53// =============================================================================
54// ROM Hash & Write Policy
55// =============================================================================
56
58 if (!rom || !rom->is_loaded()) {
59 current_rom_hash_.clear();
60 return;
61 }
63}
64
66 if (!project_ || !project_->project_opened()) {
67 return false;
68 }
69 const auto expected = NormalizeHash(project_->rom_metadata.expected_hash);
70 const auto actual = NormalizeHash(current_rom_hash_);
71 if (expected.empty() || actual.empty()) {
72 return false;
73 }
74 return expected != actual;
75}
76
78 if (!project_ || !project_->project_opened()) {
79 return absl::OkStatus();
80 }
81
82 const auto policy = project_->rom_metadata.write_policy;
83 const auto expected = NormalizeHash(project_->rom_metadata.expected_hash);
84 const auto actual = NormalizeHash(current_rom_hash_);
85
86 if (expected.empty() || actual.empty() || expected == actual) {
87 return absl::OkStatus();
88 }
89
90 if (policy == project::RomWritePolicy::kAllow) {
91 return absl::OkStatus();
92 }
93
94 if (policy == project::RomWritePolicy::kBlock) {
95 if (toast_manager_) {
97 "ROM write blocked: project expects a different ROM hash",
99 }
100 return absl::PermissionDeniedError(
101 "ROM write blocked by project write policy");
102 }
103
106 if (popup_manager_) {
108 }
109 if (toast_manager_) {
110 toast_manager_->Show("ROM hash mismatch: confirmation required to save",
112 }
113 return absl::CancelledError("ROM write confirmation required");
114 }
115
116 return absl::OkStatus();
117}
118
120 if (!rom || !rom->is_loaded()) {
121 return absl::InvalidArgumentError("ROM not loaded");
122 }
123
124 if (!project_ || !project_->project_opened() ||
127 return absl::OkStatus();
128 }
129
133 options.validate_water_fill_table = true;
134 options.validate_custom_collision_maps = true;
135 options.max_collision_errors = 6;
136
137 const auto preflight = zelda3::RunOracleRomSafetyPreflight(rom, options);
138 if (preflight.ok()) {
139 return absl::OkStatus();
140 }
141
142 const auto& first = preflight.errors.front();
143 if (toast_manager_) {
144 toast_manager_->Show(absl::StrFormat("Oracle ROM safety [%s]: %s",
145 first.code, first.message.c_str()),
147 }
148 return preflight.ToStatus();
149}
150
151// =============================================================================
152// ROM Write Confirmation State Machine
153// =============================================================================
154
159
164
165// =============================================================================
166// Pot Item Save Confirmation
167// =============================================================================
168
170 int total_rooms) {
172 pending_pot_item_unloaded_rooms_ = unloaded_rooms;
173 pending_pot_item_total_rooms_ = total_rooms;
174}
175
178 PotItemSaveDecision decision) {
182
183 if (decision == PotItemSaveDecision::kCancel) {
184 return decision;
185 }
186
189 }
191 return decision;
192}
193
194// =============================================================================
195// Backup Management
196// =============================================================================
197
198std::vector<RomFileManager::BackupEntry> RomLifecycleManager::GetRomBackups(
199 Rom* rom) const {
200 if (!rom || !rom_file_manager_) {
201 return {};
202 }
203 return rom_file_manager_->ListBackups(rom->filename());
204}
205
207 if (!rom) {
208 return absl::FailedPreconditionError("No ROM loaded");
209 }
210 if (!rom_file_manager_) {
211 return absl::FailedPreconditionError("No ROM file manager");
212 }
214}
215
217 bool enabled, const std::string& folder, int retention_count,
218 bool keep_daily, int keep_daily_days) {
219 if (!rom_file_manager_) return;
225}
226
227} // 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:28
auto filename() const
Definition rom.h:145
auto data() const
Definition rom.h:139
auto size() const
Definition rom.h:138
bool is_loaded() const
Definition rom.h:132
bool HasProjectRegistry() const
bool loaded() const
Check if the manifest has been loaded.
void Show(const char *name)
void SetBackupRetentionCount(int count)
absl::Status PruneBackups(const std::string &rom_filename) const
std::vector< BackupEntry > ListBackups(const std::string &rom_filename) const
void SetBackupBeforeSave(bool enabled)
void SetBackupFolder(const std::string &folder)
void SetBackupKeepDaily(bool enabled)
void UpdateCurrentRomHash(Rom *rom)
Recompute the hash of the current ROM.
std::vector< RomFileManager::BackupEntry > GetRomBackups(Rom *rom) const
void SetPotItemConfirmPending(int unloaded_rooms, int total_rooms)
Set pot-item confirmation pending (called by SaveRom when needed).
bool IsRomHashMismatch() const
Check whether the ROM hash mismatches the project's expected hash.
PotItemSaveDecision ResolvePotItemSaveConfirmation(PotItemSaveDecision decision)
absl::Status CheckRomWritePolicy(Rom *rom)
Enforce project write policy; may set pending_rom_write_confirm.
absl::Status CheckOracleRomSafetyPreSave(Rom *rom)
Run Oracle-specific ROM safety preflight before saving.
void ApplyDefaultBackupPolicy(bool enabled, const std::string &folder, int retention_count, bool keep_daily, int keep_daily_days)
Apply default backup policy from user settings.
void Show(const std::string &message, ToastType type=ToastType::kInfo, float ttl_seconds=3.0f)
constexpr const char * kRomWriteConfirm
Editors are the view controllers for the application.
std::string ComputeRomHash(const uint8_t *data, size_t size)
Definition rom_hash.cc:70
OracleRomSafetyPreflightResult RunOracleRomSafetyPreflight(Rom *rom, const OracleRomSafetyPreflightOptions &options)
std::string expected_hash
Definition project.h:107
RomWritePolicy write_policy
Definition project.h:108
bool project_opened() const
Definition project.h:285
core::HackManifest hack_manifest
Definition project.h:160