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"
32 std::filesystem::path path(value);
33 path = path.lexically_normal();
34 path.make_preferred();
39 absl::AsciiStrToLower(&value);
43bool PathsMatch(
const std::string& lhs,
const std::string& rhs) {
44 if (lhs.empty() || rhs.empty()) {
49 if (normalized_lhs == normalized_rhs) {
52 return Lowercase(std::filesystem::path(normalized_lhs).filename().
string()) ==
53 Lowercase(std::filesystem::path(normalized_rhs).filename().
string());
61 bool matches_configured_project =
false;
62 bool matches_editable_target =
false;
63 bool matches_build_output =
false;
75 const auto canonical_rom = std::filesystem::canonical(development_rom, ec);
76 return ec ? development_rom :
NormalizePath(canonical_rom.string());
94 const std::string& loaded_path) {
127 : rom_file_manager_(deps.rom_file_manager),
128 session_coordinator_(deps.session_coordinator),
129 toast_manager_(deps.toast_manager),
130 popup_manager_(deps.popup_manager),
131 project_(deps.project) {}
158 const std::string& source_path)
const {
167 return source.matches_editable_target && !source.matches_build_output;
175 if ((target_info.matches_editable_target ||
177 !target_info.matches_build_output) {
180 const std::string expected(
190 return absl::OkStatus();
194 if (!target_info.matches_build_output) {
195 return absl::OkStatus();
200 return absl::OkStatus();
204 return absl::OkStatus();
207 const std::string editable_target = GetEditableTargetPath(target_info);
210 absl::StrFormat(
"Project opened a build-output ROM; edit '%s' instead",
214 return absl::FailedPreconditionError(absl::StrFormat(
215 "Loaded ROM '%s' matches the project's build output. Edit '%s' instead.",
216 target_info.loaded_path.empty() ? rom->
filename()
217 : target_info.loaded_path,
223 if (!open_status.ok()) {
230 return absl::OkStatus();
237 return absl::FailedPreconditionError(absl::StrFormat(
238 "Project source binding requires the manifest development ROM %s; "
239 "cannot swap to %s. Keep editing the development ROM with Save ROM, "
240 "then use Build Project. Save As copies do not change this source "
241 "binding. The copy and project binding were kept.",
244 return absl::OkStatus();
248 Rom* rom,
const std::optional<std::string>& target_filename) {
250 return absl::OkStatus();
254 const std::string target_path =
255 target_filename.has_value()
259 const std::string source_path =
261 const auto target_info = GetRomTargetInfo(
project_, target_path);
262 const auto source_info = GetRomTargetInfo(
project_, source_path);
263 if (target_info.matches_build_output) {
265 return absl::OkStatus();
270 "ROM write blocked: '%s' is the project's build output",
271 target_info.loaded_path.empty() ? target_path
272 : target_info.loaded_path),
275 return absl::PermissionDeniedError(absl::StrFormat(
276 "ROM write blocked: '%s' is the project's build output. Edit '%s' "
278 target_info.loaded_path.empty() ? target_path : target_info.loaded_path,
279 GetEditableTargetPath(target_info)));
283 !source_info.matches_build_output) {
284 return absl::OkStatus();
287 const std::string expected(
292 return absl::OkStatus();
296 return absl::OkStatus();
302 "ROM write blocked: project expects a different ROM hash",
305 return absl::PermissionDeniedError(
306 "ROM write blocked by project write policy");
318 return absl::CancelledError(
"ROM write confirmation required");
321 return absl::OkStatus();
326 return absl::InvalidArgumentError(
"ROM not loaded");
330 return absl::OkStatus();
338 const std::string manifest_path =
343 "Save blocked: configured hack manifest is unavailable: %s",
347 return absl::FailedPreconditionError(absl::StrFormat(
348 "Configured hack manifest is missing or malformed: %s", manifest_path));
353 return absl::OkStatus();
364 if (preflight.ok()) {
365 return absl::OkStatus();
368 const auto& first = preflight.errors.front();
371 first.code, first.message.c_str()),
374 return preflight.ToStatus();
434 return absl::FailedPreconditionError(
"No ROM loaded");
437 return absl::FailedPreconditionError(
"No ROM file manager");
443 const std::string& folder,
446 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)
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_
absl::Status CheckRomWritePolicy(Rom *rom, const std::optional< std::string > &target_filename=std::nullopt)
Enforce project write policy; may set pending_rom_write_confirm.
const project::YazeProject * project_
int pending_pot_item_total_rooms_
bool pending_pot_item_save_confirm_
absl::Status CheckRomRebindPolicy(Rom *rom)
bool IsRomHashMismatch() const
Check whether the ROM hash mismatches the project's expected hash.
RomFileManager * rom_file_manager_
void ActivateRomIdentity(const RomSession *session)
PopupManager * popup_manager_
void CancelRomWriteConfirm()
std::string current_rom_path_
bool HasEditableSource(const std::string &source_path) const
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_
util::RomIdentityHashes current_rom_identity_
std::string current_rom_editing_source_path_
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_
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_
static bool PathsReferToSameBackingFile(const std::string &lhs, const std::string &rhs)
void Show(const std::string &message, ToastType type=ToastType::kInfo, float ttl_seconds=3.0f, std::string action_label={}, std::function< void()> on_action=nullptr)
std::string NormalizePath(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.
OracleRomSafetyPreflightResult RunOracleRomSafetyPreflight(Rom *rom, const OracleRomSafetyPreflightOptions &options)
SessionCoordinator * session_coordinator
RomFileManager * rom_file_manager
project::YazeProject * project
PopupManager * popup_manager
ToastManager * toast_manager
Represents a single session, containing a ROM and its associated editors.
std::optional< RomBaselineIdentity > rom_baseline
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 hack_manifest_file
std::string GetAbsolutePath(const std::string &relative_path) const
RomHashMatch Match(std::string_view expected) const
bool validate_custom_collision_maps
bool require_custom_collision_write_support
bool require_water_fill_reserved_region
bool validate_water_fill_table