diff --git a/firmware/application/external/waterfall_designer/ui_waterfall_designer.hpp b/firmware/application/external/waterfall_designer/ui_waterfall_designer.hpp index e1fadf5fe..36cf2ebf4 100644 --- a/firmware/application/external/waterfall_designer/ui_waterfall_designer.hpp +++ b/firmware/application/external/waterfall_designer/ui_waterfall_designer.hpp @@ -217,18 +217,31 @@ class WaterfallDesignerView : public View { void restore_current_profile(); void on_create_new_profile(); void on_open_profile(); - void on_profile_changed(std::filesystem::path new_profile_path); + void on_profile_changed(const std::filesystem::path& new_profile_path); void on_save_profile(); void on_add_level(); void on_remove_level(); void on_edit_color(); + /* Each of these owns the only File in its call chain. Keeping them as + * separate frames matters: a File carries a 512 byte FIL sector cache + * (_FS_TINY is 0) and the M0 process stack is 4kB, so if read_profile_file + * merged into on_profile_changed its 784 byte frame would stay live across + * the copy_file() in on_apply_current_to_wtf() - 3.6kB of 4kB instead of + * 2.8kB. GCC does not inline them at -O2 today; noinline just pins that so + * a heuristic change can't quietly eat the headroom. */ + __attribute__((noinline)) bool read_profile_file(const std::filesystem::path& path); + __attribute__((noinline)) bool write_profile_file(const std::filesystem::path& path); + void refresh_menu_view(); void on_apply_current_to_wtf(); // will restore if didn't apple, when distruct void on_apply_setting(); // apply set bool if_apply_setting{false}; + bool backup_attempted_{false}; + bool profile_backed_up_{false}; + std::filesystem::path pending_profile_path{}; // set by the New dialog, consumed on_pop /*NB: this works as: each time you change color, it apply as file realtime