10#include <initializer_list>
17#include <TargetConditionals.h>
20#include "absl/status/status.h"
21#include "absl/strings/match.h"
22#include "absl/strings/str_format.h"
23#include "imgui/imgui.h"
59#ifdef YAZE_ENABLE_TESTING
74 for (
auto it = editors_.rbegin(); it != editors_.rend(); ++it) {
75 (*it)->RollbackSaveTransaction();
81 if (editor ==
nullptr) {
82 return absl::OkStatus();
85 editors_.push_back(editor);
86 return absl::OkStatus();
90 for (
Editor* editor : editors_) {
91 editor->CommitSaveTransaction();
98 bool committed_ =
false;
102 std::initializer_list<const char*> keys) {
103 for (
const char* key : keys) {
119 std::string* warning) {
120 if (project ==
nullptr) {
131 const auto& defaults =
134 if (defaults.empty()) {
139 if (warning !=
nullptr) {
140 *warning = absl::StrFormat(
141 "Project defines custom_objects_folder but is missing "
142 "custom_object_files[0x%02X]. Seeded default mapping (%d entries).",
150 std::vector<std::string> warnings;
155 const auto rom_size = rom.
size();
156 auto warn = [&](
const std::string& message) {
157 warnings.push_back(message);
160 auto check_range = [&](
const std::string& label, uint32_t addr,
size_t span) {
161 const size_t addr_size =
static_cast<size_t>(addr);
162 if (addr_size >= rom_size || addr_size + span > rom_size) {
163 warn(absl::StrFormat(
"ROM override '%s' out of range: 0x%X (size 0x%X)",
164 label, addr, rom_size));
168 for (
const auto& [key, value] : overrides.
addresses) {
169 check_range(key, value, 1);
176 constexpr uint32_t kExpandedMessageStartDefault = 0x178000;
177 constexpr uint32_t kExpandedMessageEndDefault = 0x17FFFF;
178 const uint32_t start =
180 .value_or(kExpandedMessageStartDefault);
183 .value_or(kExpandedMessageEndDefault);
184 if (start >= rom_size || end >= rom_size) {
185 warn(absl::StrFormat(
186 "Expanded message range out of ROM bounds: 0x%X-0x%X", start, end));
187 }
else if (end < start) {
188 warn(absl::StrFormat(
"Expanded message range invalid: 0x%X-0x%X", start,
196 if (*hook < rom_size) {
198 if (opcode.ok() && opcode.value() != 0x22) {
199 warn(absl::StrFormat(
200 "Expanded music hook at 0x%X is not a JSL opcode (0x%02X)", *hook,
220 const uint32_t marker =
223 const uint32_t magic =
226 check_range(
"overworld_ptr_marker", marker, 1);
227 if (marker < rom_size) {
228 if (rom.
data()[marker] !=
static_cast<uint8_t
>(magic)) {
229 warn(absl::StrFormat(
230 "Overworld expanded pointer marker mismatch at 0x%X: expected "
231 "0x%02X, found 0x%02X",
232 marker,
static_cast<uint8_t
>(magic), rom.
data()[marker]));
242 const uint32_t flag_addr =
246 check_range(
"overworld_entrance_flag_expanded", flag_addr, 1);
247 if (flag_addr < rom_size && rom.
data()[flag_addr] == 0xB8) {
249 absl::StrFormat(
"Overworld entrance flag at 0x%X is still 0xB8 "
250 "(vanilla); expanded entrance tables may be ignored",
267 flags.overworld.kSaveOverworldEntrances =
277 session->feature_flags = flags;
300 LOG_INFO(
"EditorManager",
"ROM load options applied: preset=%s",
309 [
this](
bool visible,
bool expanded) {
321 [
this](
float width) {
328 const std::string& category) {
329 if (category.empty() ||
338 if (it != prefs.panel_visibility_state.end()) {
348 bool any_visible =
false;
349 for (
const auto& desc :
351 if (desc.visibility_flag && *desc.visibility_flag) {
371 [
this](
const std::string& category) ->
Editor* {
378 [
this](
const std::string& category) {
386 [
this](
const std::string& category) {
391 if (category ==
"Agent") {
392#ifdef YAZE_BUILD_AGENT_UI
407 [
this](
const std::string& category,
const std::string& path) {
408 if (category ==
"Assembly") {
410 editor_set->ChangeActiveAssemblyFile(path);
418 auto load_from_path = [
this](
const std::string& file_name) -> absl::Status {
419 if (file_name.empty()) {
420 return absl::OkStatus();
424 if (absl::EndsWith(file_name,
".yaze") ||
425 absl::EndsWith(file_name,
".zsproj") ||
426 absl::EndsWith(file_name,
".yazeproj")) {
432 if (!path_status.ok()) {
442 const std::optional<size_t> previous_session_id =
444 const size_t previous_session_count =
447 std::move(temp_rom), file_name);
448 if (!session_or.ok()) {
449 return session_or.status();
465#ifdef YAZE_ENABLE_TESTING
470 const auto& recent_files = manager.GetRecentFiles();
471 const bool is_first_time_rom_path =
472 std::find(recent_files.begin(), recent_files.end(), file_name) ==
475 if (!asset_status.ok()) {
476 auto rollback_status =
479 if (!rollback_status.ok()) {
480 return absl::InternalError(
481 absl::StrFormat(
"%s; session rollback failed: %s",
482 asset_status.message(), rollback_status.message()));
487 manager.AddFile(file_name);
498 return absl::OkStatus();
501#if defined(__APPLE__) && TARGET_OS_IOS == 1
508 return absl::OkStatus();
512 return load_from_path(file_name);
517 const std::optional<std::string>& save_as_filename) {
520 if (!current_rom || !current_editor_set) {
521 return absl::FailedPreconditionError(
"No ROM or editor set loaded");
524 if (save_as_filename.has_value() && save_as_filename->empty()) {
525 return absl::InvalidArgumentError(
"No filename provided for save as");
527 if (save_as_filename.has_value()) {
544 struct LifecycleProjectContextGuard {
547 ~LifecycleProjectContextGuard() {
563 const bool pending_palettes =
564 save_session !=
nullptr &&
565 palette_manager.HasUnsavedChanges(&save_session->game_data);
568 const bool palette_save_enabled =
571 if (pending_palettes && !palette_save_enabled) {
572 return absl::FailedPreconditionError(
573 "Save blocked: palette edits are pending, but palette saving is "
574 "disabled. Enable Save All Palettes or Save Dungeon Palettes, or undo "
575 "the palette edits before saving the ROM.");
577 const bool pending_gfx_groups =
578 save_session !=
nullptr && save_session->HasPendingGfxGroupChanges();
580 return absl::FailedPreconditionError(
581 "Save blocked: blockset/spriteset (gfx group) edits are pending, but "
582 "Save Gfx Groups is disabled. Enable it, or undo the gfx group edits "
583 "before saving the ROM.");
586 if (current_editor_set->HasPendingGraphicsChanges() &&
588 return absl::FailedPreconditionError(
589 "Save blocked: graphics sheet edits are pending, but Save Graphics "
590 "Sheets is disabled. Enable it, or discard the graphics sheet edits "
591 "before saving the ROM.");
599 std::vector<std::pair<uint32_t, uint32_t>> predicted_screen_write_ranges;
600 if (screen_editor !=
nullptr && (screen_editor->IsRomBackedStateValid() ||
601 screen_editor->HasPendingScreenChanges())) {
603 for (
const auto& write : plan.writes) {
604 predicted_screen_write_ranges.emplace_back(
605 write.pc_address, write.pc_address + write.data.size());
611 return absl::CancelledError(
"Save pending confirmation");
620 const auto experiment_policy =
624 const bool force_experimental_backup =
626 experiment_policy.experimental &&
627 experiment_policy.disabled_save_posture ==
629 if (force_experimental_backup) {
631 "Experimental editor save: backup forced before writing the ROM",
637 force_experimental_backup,
656 const auto predicted_dungeon_write_ranges =
657 current_editor_set->CollectDungeonWriteRanges();
660 ScopedEditorSaveTransactions editor_transactions;
662 auto save_editor = [&editor_transactions](
Editor* editor) -> absl::Status {
663 if (editor ==
nullptr) {
664 return absl::OkStatus();
667 return editor->Save();
673 if (screen_editor !=
nullptr && (screen_editor->IsRomBackedStateValid() ||
674 screen_editor->HasPendingScreenChanges())) {
687 if (pending_palettes &&
688 palette_manager.HasUnsavedChanges(&save_session->game_data)) {
721 std::vector<std::pair<uint32_t, uint32_t>> write_ranges;
722 bool diff_computed =
false;
724 if (!current_rom->filename().empty()) {
725 std::ifstream file(current_rom->filename(), std::ios::binary);
726 if (file.is_open()) {
727 file.seekg(0, std::ios::end);
728 const std::streampos end = file.tellg();
730 std::vector<uint8_t> disk_data(
static_cast<size_t>(end));
731 file.seekg(0, std::ios::beg);
732 file.read(
reinterpret_cast<char*
>(disk_data.data()),
733 static_cast<std::streamsize
>(disk_data.size()));
735 diff_computed =
true;
737 current_rom->vector());
738 if (!diff.ranges.empty()) {
740 "ROM save diff: %zu bytes changed in %zu range(s)",
741 diff.total_bytes_changed, diff.ranges.size());
742 write_ranges = std::move(diff.ranges);
749 if (write_ranges.empty() && !diff_computed) {
750 write_ranges = predicted_dungeon_write_ranges;
751 write_ranges.insert(write_ranges.end(),
752 predicted_screen_write_ranges.begin(),
753 predicted_screen_write_ranges.end());
756 if (!write_ranges.empty()) {
759 if (!conflicts.empty()) {
766 "Save paused: %zu write conflict(s) with ASM hooks",
769 return absl::CancelledError(
"Write conflict confirmation required");
782 std::filesystem::path collision_source;
783 if (!save_as_filename.has_value() && save_project->
project_opened() &&
786 std::error_code same_ec;
787 if (std::filesystem::equivalent(
789 current_rom->filename(), same_ec)) {
795 save_as_filename.has_value()
798 if (save_status.ok()) {
799 editor_transactions.Commit();
804 session->backup_restore_pending =
false;
810 if (save_as_filename.has_value()) {
813 session->filepath = *save_as_filename;
818 manager.AddFile(*save_as_filename);
831 std::string project_rom_path = pending_selection.has_value()
832 ? pending_selection->candidate_path
834 const std::string previous_project_rom_path =
835 pending_selection.has_value() ? pending_selection->previous_path
837 bool persist_selected_rom = pending_selection.has_value();
838 auto abandon_selected_rom = [&]() {
839 if (!persist_selected_rom) {
847 if (project_rom_path.empty()) {
850 "Project has no ROM file configured. Please select a ROM.",
852#if defined(__APPLE__) && TARGET_OS_IOS == 1
862 if (bundle_parent.extension() ==
".yazeproj") {
864 "ROM is downloading from iCloud. Reopen the project in a few "
867 return absl::UnavailableError(
868 "Project ROM is not available from iCloud yet");
872 const std::optional<size_t> target_session_id =
877 [
this, target_project_filepath, target_session_id,
878 selection_generation](
const std::string& rom_path) {
883 "ROM selection ignored because the active project changed",
884 ToastType::kWarning);
887 const bool restore_pending_transition =
889 const std::optional<size_t> previous_session_id =
891 auto restore_after_failure = [&]() {
892 if (restore_pending_transition) {
896 if (rom_path.empty()) {
897 restore_after_failure();
902 if (!path_status.ok()) {
905 restore_after_failure();
909 if (!selection_status.ok()) {
911 absl::StrFormat(
"Failed to update project ROM: %s",
912 selection_status.message()),
914 restore_after_failure();
920 absl::StrFormat(
"Failed to load project ROM: %s",
923 restore_after_failure();
926 return absl::OkStatus();
930 if (rom_path.empty()) {
931 return absl::CancelledError(
"Project ROM selection cancelled");
934 project_rom_path = rom_path;
935 persist_selected_rom =
true;
939 auto backing_status =
941 if (!backing_status.ok()) {
942 abandon_selected_rom();
943 return backing_status;
949 if (!load_status.ok()) {
952 absl::StrFormat(
"Could not load ROM '%s': %s. Please select a new ROM.",
953 project_rom_path, load_status.message()),
955#if defined(__APPLE__) && TARGET_OS_IOS == 1
956 abandon_selected_rom();
962 auto rom_parent = std::filesystem::path(project_rom_path).parent_path();
963 if (rom_parent.extension() ==
".yazeproj") {
965 "ROM is still downloading from iCloud. Try reopening the project "
968 return absl::UnavailableError(
969 "Project ROM is still downloading from iCloud");
973 const std::optional<size_t> target_session_id =
978 [
this, target_project_filepath, target_session_id,
979 selection_generation](
const std::string& rom_path) {
984 "ROM selection ignored because the active project changed",
985 ToastType::kWarning);
988 const bool restore_pending_transition =
990 const std::optional<size_t> previous_session_id =
992 auto restore_after_failure = [&]() {
993 if (restore_pending_transition) {
997 if (rom_path.empty()) {
998 restore_after_failure();
1003 if (!path_status.ok()) {
1006 restore_after_failure();
1010 if (!selection_status.ok()) {
1012 absl::StrFormat(
"Failed to update project ROM: %s",
1013 selection_status.message()),
1015 restore_after_failure();
1021 absl::StrFormat(
"Failed to load project ROM: %s",
1024 restore_after_failure();
1027 return absl::OkStatus();
1031 if (rom_path.empty()) {
1032 return absl::CancelledError(
"Project ROM selection cancelled");
1035 project_rom_path = rom_path;
1036 persist_selected_rom =
true;
1042 if (!policy_status.ok()) {
1043 abandon_selected_rom();
1044 return policy_status;
1047 if (persist_selected_rom) {
1051 const size_t previous_session_count =
1054 std::move(temp_rom), project_rom_path);
1055 if (!session_or.ok()) {
1056 abandon_selected_rom();
1057 return session_or.status();
1071 "Project has custom object data but 'enable_custom_objects' was "
1072 "disabled. Enabling at runtime.");
1076 std::string legacy_mapping_warning;
1078 &legacy_mapping_warning)) {
1079 LOG_WARN(
"EditorManager",
"%s", legacy_mapping_warning.c_str());
1081 "Seeded default custom object mapping for object 0x31 (save project "
1093 "Feature flags applied: kEnableCustomObjects=%s, "
1094 "custom_objects_folder='%s', custom_object_files=%zu entries",
1112 "Project ROM hash mismatch detected. Check ROM Identity settings.",
1115 auto warnings = ValidateRomAddressOverrides(
1117 if (!warnings.empty()) {
1118 for (
const auto& warning : warnings) {
1119 LOG_WARN(
"EditorManager",
"%s", warning.c_str());
1129#ifdef YAZE_ENABLE_TESTING
1130 LOG_DEBUG(
"EditorManager",
"Setting ROM in TestManager - %p ('%s')",
1138 const std::string absolute_code_folder =
1141#if !(defined(__APPLE__) && TARGET_OS_IOS == 1)
1142 editor_set->OpenAssemblyFolder(absolute_code_folder);
1153 if (!asset_status.ok()) {
1154 abandon_selected_rom();
1155 auto rollback_status =
1157 if (!rollback_status.ok()) {
1158 return absl::InternalError(
1159 absl::StrFormat(
"%s; session rollback failed: %s",
1160 asset_status.message(), rollback_status.message()));
1162 return asset_status;
1165 if (persist_selected_rom) {
1167 if (!save_status.ok()) {
1168 abandon_selected_rom();
1169 auto rollback_status =
1171 if (!rollback_status.ok()) {
1172 return absl::InternalError(
1173 absl::StrFormat(
"%s; session rollback failed: %s",
1174 save_status.message(), rollback_status.message()));
1233 return absl::OkStatus();
1237 Rom&& rom,
const std::string& filepath) {
1239 return absl::FailedPreconditionError(
"No session coordinator");
1243 return absl::FailedPreconditionError(
"No active ROM session");
1266 Rom previous_rom = session->rom;
1267 const std::string previous_filepath = session->filepath;
1268 const bool game_data_was_loaded = session->game_data_loaded;
1272 const bool dungeon_was_initialized =
1273 session->editor_initialized[dungeon_index];
1274 const bool dungeon_assets_were_loaded =
1275 session->editor_assets_loaded[dungeon_index];
1279 const bool screen_was_initialized = session->editor_initialized[screen_index];
1280 const bool screen_assets_were_loaded =
1281 session->editor_assets_loaded[screen_index];
1282 auto restore_dungeon_asset_state = [&]() {
1283 if (dungeon_editor) {
1284 session->editor_initialized[dungeon_index] =
1285 session->editor_initialized[dungeon_index] || dungeon_was_initialized;
1286 session->editor_assets_loaded[dungeon_index] =
1287 session->editor_assets_loaded[dungeon_index] ||
1288 dungeon_assets_were_loaded;
1291 auto restore_screen_asset_state = [&]() {
1292 if (screen_editor) {
1293 session->editor_initialized[screen_index] =
1294 session->editor_initialized[screen_index] || screen_was_initialized;
1295 session->editor_assets_loaded[screen_index] =
1296 session->editor_assets_loaded[screen_index] ||
1297 screen_assets_were_loaded;
1301 session->editors.InvalidateScreenRomBackedState();
1303 session->rom = std::move(rom);
1304 session->filepath = filepath;
1305 session->game_data.Clear();
1306 session->game_data.set_rom(&session->rom);
1307 session->editors.SetGameData(&session->game_data);
1314 if (load_status.ok() && game_data_was_loaded && !session->game_data_loaded) {
1317 if (load_status.ok() && screen_editor && screen_assets_were_loaded) {
1318 load_status = screen_editor->RefreshRomBackedState();
1320 if (load_status.ok()) {
1321 restore_screen_asset_state();
1323 if (load_status.ok() && dungeon_editor) {
1324 load_status = dungeon_editor->RefreshRomBackedState();
1325 if (load_status.ok()) {
1326 restore_dungeon_asset_state();
1329 if (!load_status.ok()) {
1332 session->editors.InvalidateScreenRomBackedState();
1334 session->rom = std::move(previous_rom);
1335 session->filepath = previous_filepath;
1336 session->game_data.Clear();
1337 session->game_data.set_rom(&session->rom);
1338 session->editors.SetGameData(&session->game_data);
1345 if (game_data_was_loaded && !session->game_data_loaded) {
1347 if (rollback_status.ok()) {
1348 rollback_status = game_data_status;
1351 if (screen_editor && screen_assets_were_loaded) {
1352 auto screen_status = screen_editor->RefreshRomBackedState();
1353 if (screen_status.ok()) {
1354 restore_screen_asset_state();
1356 if (rollback_status.ok()) {
1357 rollback_status = screen_status;
1360 restore_screen_asset_state();
1362 if (dungeon_editor) {
1363 auto dungeon_status = dungeon_editor->RefreshRomBackedState();
1364 if (dungeon_status.ok()) {
1365 restore_dungeon_asset_state();
1367 if (rollback_status.ok()) {
1368 rollback_status = dungeon_status;
1372 if (!rollback_status.ok()) {
1373 return absl::InternalError(absl::StrFormat(
1374 "ROM reload failed (%s) and restoring prior assets failed (%s)",
1375 load_status.message(), rollback_status.message()));
1381 return absl::OkStatus();
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
absl::StatusOr< uint8_t > ReadByte(int offset) const
static TimingManager & Get()
float GetElapsedTime() const
Get total elapsed time since first update.
std::vector< WriteConflict > AnalyzePcWriteRanges(const std::vector< std::pair< uint32_t, uint32_t > > &pc_ranges) const
Analyze a set of PC-offset ranges for write conflicts.
bool loaded() const
Check if the manifest has been loaded.
bool AdoptExistingRepository()
DungeonEditorV2 - Simplified dungeon editor using component delegation.
std::unique_ptr< SessionCoordinator > session_coordinator_
RomLifecycleManager rom_lifecycle_
void SwitchToEditor(EditorType editor_type, bool force_visible=false, bool from_dialog=false) override
project::YazeProject current_project_
absl::Status LoadProjectWithRom()
absl::Status LoadAssetsForMode(uint64_t loading_handle=0)
float settings_dirty_timestamp_
absl::Status CheckRomWritePolicy(const std::optional< std::string > &target_filename=std::nullopt)
Save the current ROM file.
bool active_project_build_reported_
absl::Status EnsureGameDataLoaded()
bool pending_project_open_transition_
Rom * GetCurrentRom() const override
void ResetAssetState(RomSession *session)
core::VersionManager * version_manager_
void SyncEditorContextForCategory(const std::string &category)
Editor * ResolveEditorForCategory(const std::string &category)
absl::Status FinalizeNewProject(const std::string &project_name, const std::string &project_path=std::string())
void SetupDialogCallbacks()
ToastManager toast_manager_
FeatureHintManager feature_hint_manager_
absl::Status OpenRomOrProjectInternal(const std::string &filename)
auto GetCurrentEditorSet() const -> EditorSet *
uint64_t project_rom_selection_generation_
void HandleSessionRomLoaded(size_t index, Rom *rom)
void RestoreCurrentRomIdentity()
WorkspaceWindowManager window_manager_
bool show_rom_load_options_
absl::Status SaveRomInternal(const std::optional< std::string > &save_as_filename)
void MaybeEmitZScreamRomLoadHints()
std::optional< size_t > pending_project_open_previous_session_id_
void CaptureActiveProjectContext()
std::optional< size_t > active_project_context_session_id_
RomLoadOptionsDialog rom_load_options_dialog_
void BindProjectContextToSession(RomSession *session, const project::YazeProject &project)
void ApplyCurrentProjectRuntimeContext()
void RefreshHackWorkflowBackend()
void SetupSidebarCallbacks()
size_t GetCurrentSessionIndex() const
void ShowPostLoadSurface()
size_t GetCurrentSessionId() const
Stable workspace identity; unlike the UI index, it does not compact.
absl::Status ValidateProjectRomSelection(const std::string &rom_path)
void ConfigureSession(RomSession *session) override
bool IsRomHashMismatch() const
void RefreshResourceLabelProvider()
std::unique_ptr< BackgroundCommandTask > active_project_build_
UserSettings user_settings_
void ConfigureEditorDependencies(EditorSet *editor_set, Rom *rom, size_t session_id)
absl::StatusOr< const project::YazeProject * > PrepareActiveProjectContextForSave()
std::unique_ptr< ProjectManagementPanel > project_management_panel_
void RestoreProjectContextAfterFailedOpen(std::optional< size_t > previous_session_id)
absl::Status CheckOracleRomSafetyPreSave(Rom *rom)
absl::Status LoadRomInternal()
AssetLoadMode asset_load_mode_
absl::Status DiscardProvisionalSessionCreatedSince(size_t previous_session_count)
absl::Status EnsureEditorAssetsLoaded(EditorType type)
std::unique_ptr< PopupManager > popup_manager_
bool RestoreProjectContextForSession(RomSession *session)
void CaptureCurrentRomIdentity(bool preserve_editing_source=false)
std::unique_ptr< UICoordinator > ui_coordinator_
std::optional< PendingProjectRomSelection > pending_project_rom_selection_
RomFileManager rom_file_manager_
absl::Status ReplaceActiveSessionRom(Rom &&rom, const std::string &filepath)
static EditorType GetEditorTypeFromCategory(const std::string &category)
static EditorExperimentPolicy GetExperimentPolicy(EditorType type)
Interface for editor classes.
virtual absl::Status BeginSaveTransaction()
bool MaybeShow(std::string_view id)
static std::vector< std::string > GetDefaultWindows(EditorType type)
Main UI class for editing overworld maps in A Link to the Past.
absl::Status SaveRom(Rom *rom, const std::filesystem::path &collision_source={})
absl::Status LoadRom(Rom *rom, const std::string &filename)
absl::Status SaveRomAs(Rom *rom, const std::string &filename)
Manages ROM and project persistence state.
void SetProjectContext(const project::YazeProject *project)
bool ShouldBypassWriteConflict() const
void CancelRomWriteConfirm()
absl::Status CheckRomOpenPolicy(Rom *rom)
Validate that the loaded ROM is a safe project target to open/edit.
void ConsumeWriteConflictBypass()
const std::vector< core::WriteConflict > & pending_write_conflicts() const
void SetPendingWriteConflicts(std::vector< core::WriteConflict > conflicts)
bool IsRomWriteConfirmPending() const
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 Open(Rom *rom, const std::string &rom_filename)
Open the dialog after ROM detection.
void SetConfirmCallback(std::function< void(const LoadOptions &)> callback)
Set callback for when options are confirmed.
The ScreenEditor class allows the user to edit a variety of screens in the game or create a custom me...
void ClearProjectWorkflowStatus()
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)
void EnableFileBrowser(const std::string &category, const std::string &root_path="")
size_t GetActiveSessionId() const
std::vector< WindowDescriptor > GetWindowsInCategory(size_t session_id, const std::string &category) const
void SetEditorResolver(std::function< Editor *(const std::string &)> resolver)
void RestoreVisibilityState(size_t session_id, const std::unordered_map< std::string, bool > &state, bool publish_events=false)
Restore panel visibility state from persistence.
void SetPanelBrowserCategoryWidthChangedCallback(std::function< void(float)> cb)
void SetSidebarStateChangedCallback(std::function< void(bool, bool)> cb)
static constexpr const char * kDashboardCategory
void SetCategoryChangedCallback(std::function< void(const std::string &)> cb)
void SetFileBrowserPath(const std::string &category, const std::string &path)
void SetOnWindowCategorySelectedCallback(std::function< void(const std::string &)> callback)
void SetOnWindowClickedCallback(std::function< void(const std::string &)> callback)
bool OpenWindow(size_t session_id, const std::string &base_window_id)
void SetSidePanelWidthChangedCallback(std::function< void(float)> cb)
void SetFileClickedCallback(std::function< void(const std::string &category, const std::string &path)> callback)
ScopedEditorSaveTransactions & operator=(const ScopedEditorSaveTransactions &)=delete
absl::Status Begin(Editor *editor)
ScopedEditorSaveTransactions()=default
~ScopedEditorSaveTransactions()
std::vector< Editor * > editors_
ScopedEditorSaveTransactions(const ScopedEditorSaveTransactions &)=delete
void ActivateSession(zelda3::GameData *game_data)
Select the palette state for a ROM session without resnapshotting it.
static PaletteManager & Get()
Get the singleton instance.
void ReleaseSession(const zelda3::GameData *game_data)
Forget all palette tracking for a closing or reloaded ROM session.
static RecentFilesManager & GetInstance()
void SetCurrentRom(Rom *rom)
static TestManager & Get()
static void ShowOpenFileDialogAsync(const FileDialogOptions &options, std::function< void(const std::string &)> callback)
static std::string ShowOpenFileDialog()
ShowOpenFileDialog opens a file dialog and returns the selected filepath. Uses global feature flag to...
static const std::vector< std::string > & DefaultSubtypeFilenamesForObject(int object_id)
void RefreshFeatureFlagMappings()
static DrawRoutineRegistry & Get()
static OverworldVersion GetVersion(const Rom &rom)
Detect ROM version from ASM marker byte.
int main(int argc, char **argv)
#define LOG_DEBUG(category, format,...)
#define LOG_WARN(category, format,...)
#define LOG_INFO(category, format,...)
#define ASSIGN_OR_RETURN(type_variable_name, expression)
constexpr char kOverworldExpandedPtrHigh[]
constexpr char kOverworldEntrancePosExpanded[]
constexpr char kExpandedMusicHook[]
constexpr char kExpandedMusicMain[]
constexpr char kOverworldExpandedPtrMagic[]
constexpr char kExpandedMessageEnd[]
constexpr char kOverworldExpandedPtrMarker[]
constexpr char kOverworldEntranceMapExpanded[]
constexpr char kOverworldEntranceFlagExpanded[]
constexpr char kExpandedMessageStart[]
constexpr char kOverworldEntranceIdExpanded[]
constexpr char kOverworldExpandedPtrLow[]
constexpr char kExpandedMusicAux[]
void ClearWorkflowHistory()
void SetEditorWindowContext(const std::string &category, Editor *editor)
void SetBuildWorkflowStatus(const ProjectWorkflowStatus &status)
void SetBuildWorkflowLog(const std::string &output)
void SetRunWorkflowStatus(const ProjectWorkflowStatus &status)
void SetCurrentProject(::yaze::project::YazeProject *project)
Set the current project instance.
constexpr const char * kZScreamZso
constexpr const char * kZScreamWelcome
constexpr const char * kZScreamProjects
bool ProjectUsesCustomObjects(const project::YazeProject &project)
bool HasAnyOverride(const core::RomAddressOverrides &overrides, std::initializer_list< const char * > keys)
constexpr int kTrackCustomObjectId
bool SeedLegacyTrackObjectMapping(project::YazeProject *project, std::string *warning)
std::vector< std::string > ValidateRomAddressOverrides(const core::RomAddressOverrides &overrides, const Rom &rom)
Editors are the view controllers for the application.
size_t EditorTypeIndex(EditorType type)
DiffSummary ComputeDiffRanges(const std::vector< uint8_t > &before, const std::vector< uint8_t > &after)
FileDialogOptions MakeRomFileDialogOptions(bool include_all_files)
absl::Status SaveGfxGroups(Rom &rom, const GameData &data)
absl::Status LoadGameData(Rom &rom, GameData &data, const LoadOptions &options)
Loads all Zelda3-specific game data from a generic ROM.
constexpr int kExpandedPtrTableMarker
@ kVanilla
0xFF in ROM, no ZScream ASM applied
constexpr uint8_t kExpandedPtrTableMagic
constexpr int kOverworldEntranceExpandedFlagPos
#define RETURN_IF_ERROR(expr)
bool kEnableCustomObjects
struct yaze::core::FeatureFlags::Flags::Dungeon dungeon
std::unordered_map< std::string, uint32_t > addresses
std::optional< uint32_t > GetAddress(const std::string &key) const
bool save_overworld_items
std::string selected_preset
bool save_overworld_exits
bool enable_custom_overworld
bool save_overworld_entrances
Represents a single session, containing a ROM and its associated editors.
core::FeatureFlags::Flags feature_flags
std::optional< project::YazeProject > project_context
bool show_experimental_editors
float sidebar_panel_width
std::string sidebar_active_category
std::unordered_map< std::string, std::unordered_map< std::string, bool > > panel_visibility_state
float panel_browser_category_width
int backup_keep_daily_days
int backup_retention_count
float autosave_interval_secs
Modern project structure with comprehensive settings consolidation.
std::string rom_backup_folder
std::unordered_map< int, std::vector< std::string > > custom_object_files
std::string custom_objects_folder
bool project_opened() const
std::string git_repository
core::HackManifest hack_manifest
std::string GetDisplayName() const
WorkspaceSettings workspace_settings
std::string custom_collision_json
std::string GetAbsolutePath(const std::string &relative_path) const
core::FeatureFlags::Flags feature_flags
core::RomAddressOverrides rom_address_overrides