9#include "absl/status/status.h"
10#include "absl/strings/ascii.h"
11#include "absl/strings/match.h"
12#include "absl/strings/str_format.h"
27 absl::AsciiStrToLower(&value);
28 if (absl::StartsWith(value,
"0x")) {
29 value = value.substr(2);
31 value.erase(std::remove_if(value.begin(), value.end(),
32 [](
unsigned char c) { return std::isspace(c); }),
41 std::filesystem::path path(value);
42 path = path.lexically_normal();
43 path.make_preferred();
48 absl::AsciiStrToLower(&value);
52bool PathsMatch(
const std::string& lhs,
const std::string& rhs) {
53 if (lhs.empty() || rhs.empty()) {
58 if (normalized_lhs == normalized_rhs) {
61 return Lowercase(std::filesystem::path(normalized_lhs).filename().
string()) ==
62 Lowercase(std::filesystem::path(normalized_rhs).filename().
string());
70 bool matches_configured_project =
false;
71 bool matches_editable_target =
false;
72 bool matches_build_output =
false;
100 const std::string& loaded_path) {
133 : rom_file_manager_(deps.rom_file_manager),
134 session_coordinator_(deps.session_coordinator),
135 toast_manager_(deps.toast_manager),
136 popup_manager_(deps.popup_manager),
137 project_(deps.project) {}
166 if (target_info.matches_editable_target &&
167 !target_info.matches_build_output) {
172 if (expected.empty() || actual.empty()) {
175 return expected != actual;
180 return absl::OkStatus();
184 if (!target_info.matches_build_output) {
185 return absl::OkStatus();
190 return absl::OkStatus();
194 return absl::OkStatus();
197 const std::string editable_target = GetEditableTargetPath(target_info);
200 absl::StrFormat(
"Project opened a build-output ROM; edit '%s' instead",
204 return absl::FailedPreconditionError(absl::StrFormat(
205 "Loaded ROM '%s' matches the project's build output. Edit '%s' instead.",
206 target_info.loaded_path.empty() ? rom->
filename()
207 : target_info.loaded_path,
213 return absl::OkStatus();
218 if (target_info.matches_build_output) {
220 return absl::OkStatus();
225 "ROM write blocked: '%s' is the project's build output",
227 : target_info.loaded_path),
230 return absl::PermissionDeniedError(absl::StrFormat(
231 "ROM write blocked: '%s' is the project's build output. Edit '%s' "
234 : target_info.loaded_path,
235 GetEditableTargetPath(target_info)));
238 if (target_info.matches_editable_target &&
239 !target_info.matches_build_output) {
240 return absl::OkStatus();
246 if (expected.empty() || actual.empty() || expected == actual) {
247 return absl::OkStatus();
251 return absl::OkStatus();
257 "ROM write blocked: project expects a different ROM hash",
260 return absl::PermissionDeniedError(
261 "ROM write blocked by project write policy");
273 return absl::CancelledError(
"ROM write confirmation required");
276 return absl::OkStatus();
281 return absl::InvalidArgumentError(
"ROM not loaded");
287 return absl::OkStatus();
298 if (preflight.ok()) {
299 return absl::OkStatus();
302 const auto& first = preflight.errors.front();
305 first.code, first.message.c_str()),
308 return preflight.ToStatus();
368 return absl::FailedPreconditionError(
"No ROM loaded");
371 return absl::FailedPreconditionError(
"No ROM file manager");
377 const std::string& folder,
380 int keep_daily_days) {
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
bool HasProjectRegistry() const
bool loaded() const
Check if the manifest has been loaded.
const BuildPipeline & build_pipeline() const
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 SetBackupKeepDailyDays(int days)
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 pending_rom_write_confirm_
int pending_pot_item_total_rooms_
bool pending_pot_item_save_confirm_
bool IsRomHashMismatch() const
Check whether the ROM hash mismatches the project's expected hash.
std::string current_rom_hash_
RomFileManager * rom_file_manager_
PopupManager * popup_manager_
void CancelRomWriteConfirm()
std::string current_rom_path_
absl::Status CheckRomOpenPolicy(Rom *rom)
Validate that the loaded ROM is a safe project target to open/edit.
bool suppress_pot_item_save_once_
PotItemSaveDecision ResolvePotItemSaveConfirmation(PotItemSaveDecision decision)
RomLifecycleManager()=default
int pending_pot_item_unloaded_rooms_
bool bypass_build_output_open_once_
bool bypass_rom_write_confirm_once_
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.
bool bypass_pot_item_confirm_once_
void Initialize(Dependencies deps)
absl::Status PruneRomBackups(Rom *rom)
ToastManager * toast_manager_
project::YazeProject * project_
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.
SessionCoordinator * session_coordinator_
void Show(const std::string &message, ToastType type=ToastType::kInfo, float ttl_seconds=3.0f)
std::string NormalizePath(std::string value)
std::string NormalizeHash(std::string value)
std::string GetBuildOutputProjectRomPath(const project::YazeProject *project)
std::string Lowercase(std::string value)
std::string GetEditableProjectRomPath(const project::YazeProject *project)
RomTargetInfo GetRomTargetInfo(const project::YazeProject *project, const std::string &loaded_path)
bool PathsMatch(const std::string &lhs, const std::string &rhs)
std::string GetEditableTargetPath(const RomTargetInfo &info)
Editors are the view controllers for the application.
std::string ComputeRomHash(const uint8_t *data, size_t size)
OracleRomSafetyPreflightResult RunOracleRomSafetyPreflight(Rom *rom, const OracleRomSafetyPreflightOptions &options)
SessionCoordinator * session_coordinator
RomFileManager * rom_file_manager
project::YazeProject * project
PopupManager * popup_manager
ToastManager * toast_manager
std::string configured_project_path
bool matches_build_output
bool matches_editable_target
std::string build_output_path
bool matches_configured_project
std::string editable_target_path
Modern project structure with comprehensive settings consolidation.
bool project_opened() const
core::HackManifest hack_manifest
std::string GetAbsolutePath(const std::string &relative_path) const
bool validate_custom_collision_maps
bool require_custom_collision_write_support
bool require_water_fill_reserved_region
bool validate_water_fill_table