diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index a4bc88930..607e1d657 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -23,4 +23,4 @@ jobs: ref: ${{ github.event.pull_request.head.sha }} - name: "Check code formatting" - run: ./fbt lint lint_py + run: ./fbt lint_all diff --git a/.gitmodules b/.gitmodules index 30f34a33f..25b5cddd1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -8,9 +8,6 @@ [submodule "lib/mlib"] path = lib/mlib url = https://github.com/P-p-H-d/mlib.git -[submodule "lib/littlefs"] - path = lib/littlefs - url = https://github.com/littlefs-project/littlefs.git [submodule "lib/nanopb"] path = lib/nanopb url = https://github.com/nanopb/nanopb.git diff --git a/.pvsoptions b/.pvsoptions index 8606eef15..4040dcb91 100644 --- a/.pvsoptions +++ b/.pvsoptions @@ -1 +1 @@ ---ignore-ccache -C gccarm --rules-config .pvsconfig -e lib/cmsis_core -e lib/fatfs -e lib/fnv1a-hash -e lib/FreeRTOS-Kernel -e lib/heatshrink -e lib/libusb_stm32 -e lib/littlefs -e lib/mbedtls -e lib/microtar -e lib/mlib -e lib/stm32wb_cmsis -e lib/stm32wb_copro -e lib/stm32wb_hal -e lib/u8g2 -e lib/nanopb -e lib/mjs -e */arm-none-eabi/* +--ignore-ccache -C gccarm --rules-config .pvsconfig -e lib/cmsis_core -e lib/fatfs -e lib/fnv1a-hash -e lib/FreeRTOS-Kernel -e lib/heatshrink -e lib/libusb_stm32 -e lib/mbedtls -e lib/microtar -e lib/mlib -e lib/stm32wb_cmsis -e lib/stm32wb_copro -e lib/stm32wb_hal -e lib/u8g2 -e lib/nanopb -e lib/mjs -e */arm-none-eabi/* diff --git a/CHANGELOG.md b/CHANGELOG.md index d27213d72..b52232b7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,21 +1,74 @@ +### Breaking Changes: +- Desktop: Settings restructured due to removal of LFS / LittleFS Internal Storage + - You might need to reconfigure Desktop Settings (PIN code, auto lock, show clock) + - Desktop Keybinds should transfer correctly automatically + ### Added: +- Apps: + - Tools: Key Copier (by @zinongli) + - Sub-GHz: Music to Sub-GHz Radio (by @jamisonderek) +- Settings: Show free flash amount in internal storage info (by @Willy-JL) +- Services: + - OFW: On SD insert load BT, Desktop, Dolphin, Expansion, Notification, Region files (by @gsurkov) + - On SD insert also load Momentum Settings, Asset Packs, FindMy Flipper, NameSpoof, RGB Backlight, Power, SubGHz options, and migrate files (by @Willy-JL) +- Furi: Re-enabled `FURI_TRACE` since LFS removal frees DFU, will get better crash messages with source code path (by @Willy-JL) +- OFW: Sub-GHz: Add Dickert MAHS garage door protocol (by @OevreFlataeker) - OFW: RFID: Add GProxII support (by @BarTenderNZ) - OFW: iButton: Support ID writing (by @Astrrra) -- OFW: FBT: Add `-Wundef` to compiler options (by @hedger) +- OFW: GUI: Added a text input that only accepts full numbers (by @leedave) +- FBT: + - OFW: Add `-Wundef` to compiler options (by @hedger) + - OFW: Ensure that all images conform specification (by @skyhawkillusions & @hedger) + - Don't format images in external apps folder, only firmware (by @Willy-JL) ### Updated: - Apps: - - Seader: Remove some optional asn1 fields (by @bettse) - - NFC Playlist: Fix extension check and error messages (by @acegoal07) + - BLE Spam: Can use 20ms advertising again with LFS gone (by @Willy-JL) + - Seader: Remove some optional ASN1 fields, disable ASN1 debug (by @bettse) + - NFC Playlist: Fix extension check and error messages, bugfixes and improvements (by @acegoal07) + - ESP Flasher: Update Marauder bins to v1.0.0 (by @justcallmekoko) + - Sub-GHz Bruteforcer: Fix one/two byte text (by @Willy-JL) + - Pokemon Trading: Reset trade without affecting current pokemon, major refactoring (by @kbembedded) + - T5577 Raw Writer: Code refactor, bugfixes and improvements (by @zinongli) + - AirMouse: Fix compatibility with new firmwares (by @ginkage) + - Flizzer Tracker: Fix app not responding to keypresses (by @LTVA1) + - UHF RFID: Bugfixes, some refactoring, write modes (by @frux-c) + - Authenticator: Fix BT keys filenames format (by @akopachov) + - UL: UART Terminal: Configurable CRLF or newline mode (by @xMasterX) + - UL: SubGHz Bruteforcer: App refactoring and code documentation (by @derskythe) - Various app fixes for `-Wundef` option (by @Willy-JL) + - Many app fixes for deprecated `view_dispatcher_enable_queue()` (by @xMasterX & @Willy-JL) +- BadKB: Lower BLE conn interval like base HID profile (by @Willy-JL) +- Desktop: Refactor Keybinds, no more 63 character limit, only load when activated to save RAM (by @Willy-JL) +- MNTM Settings: SubGHz frequency add screen uses new NumberInput view (by @Willy-JL) +- GUI: Small tweaks to NumberInput to match Text and Byte, and for better usability (by @Willy-JL) +- Settings: + - Statusbar Clock and Left Handed options show in normal Settings app like OFW (by @Willy-JL) + - Update list of keys files for forget all devices (by @Willy-JL) +- Services: + - Big cleanup of all services and settings handling, refactor lots old code (by @Willy-JL) + - Update all settings paths to use equivalents like OFW or UL for better compatibility (by @Willy-JL) +- Updater: Change to `resources.tar.gz` filename to avoid confusion with update `.tgz` (by @Willy-JL) - OFW: NFC: Refactor detected protocols list (by @Astrrra) +- Furi: + - OFW: FuriEventLoop Pt.2 with `Mutex` `Semaphore` `StreamBuffer`, refactor Power service (by @gsurkov) + - OFW: Update string documentation (by @skotopes) - OFW: CCID: App refactor (by @kidbomb) -- OFW: Furi: Update string documentation (by @skotopes) - OFW: FBT: Toolchain v39 (by @hedger) ### Fixed: -- GUI: Fix Dark Mode after XOR canvas color, like in NFC dict attack (by @Willy-JL) -- OFW: NFC: Fix plantain balance string (by @Astrrra) +- GUI: + - Fix Dark Mode after XOR canvas color, like in NFC dict attack (by @Willy-JL) + - OFW: Make file extensions case-insensitive (by @gsurkov)) +- NFC: + - OFW: Fix plantain balance string (by @Astrrra) + - OFW: Now fifo size in ST25 chip is calculated properly (by @RebornedBrain) +- OFW: Sub-GHz: Fix RPC status for ButtonRelease event (by @Skorpionm) +- OFW: Infrared: Fix cumulative error in infrared signals (by @gsurkov) +- OFW: Desktop: Separate callbacks for dolphin and storage subscriptions (by @skotopes) +- OFW: FBT: Improved size validator for updater image (by @hedger) - OFW: JS: Ensure proper closure of variadic function in `mjs_array` (by @derskythe) ### Removed: +- OFW: Storage: Remove LFS / LittleFS Internal Storage, all config on SD Card (by @skotopes & @gsurkov) +- Storage: Remove `CFG_PATH()` and `.config/` folder, `INT_PATH()` is now on SD card at `.int/` due to LFS removal and should be used instead (by @Willy-JL) diff --git a/SConstruct b/SConstruct index 14a9426da..f404bd02e 100644 --- a/SConstruct +++ b/SConstruct @@ -322,7 +322,13 @@ firmware_env.Append( "SConstruct", "firmware.scons", "fbt_options.py", - ] + ], + IMG_LINT_SOURCES=[ + # Image assets + "applications", + "!applications/external", + "assets", + ], ) @@ -359,6 +365,39 @@ distenv.PhonyTarget( PY_LINT_SOURCES=firmware_env["PY_LINT_SOURCES"], ) +# Image assets linting +distenv.PhonyTarget( + "lint_img", + [ + [ + "${PYTHON3}", + "${FBT_SCRIPT_DIR}/imglint.py", + "check", + "${IMG_LINT_SOURCES}", + "${ARGS}", + ] + ], + IMG_LINT_SOURCES=firmware_env["IMG_LINT_SOURCES"], +) + +distenv.PhonyTarget( + "format_img", + [ + [ + "${PYTHON3}", + "${FBT_SCRIPT_DIR}/imglint.py", + "format", + "${IMG_LINT_SOURCES}", + "${ARGS}", + ] + ], + IMG_LINT_SOURCES=firmware_env["IMG_LINT_SOURCES"], +) + +distenv.Alias("lint_all", ["lint", "lint_py", "lint_img"]) +distenv.Alias("format_all", ["format", "format_py", "format_img"]) + + # Start Flipper CLI via PySerial's miniterm distenv.PhonyTarget( "cli", diff --git a/applications/debug/accessor/accessor_view_manager.cpp b/applications/debug/accessor/accessor_view_manager.cpp index 955c0b286..aeb90c297 100644 --- a/applications/debug/accessor/accessor_view_manager.cpp +++ b/applications/debug/accessor/accessor_view_manager.cpp @@ -5,45 +5,49 @@ AccessorAppViewManager::AccessorAppViewManager() { event_queue = furi_message_queue_alloc(10, sizeof(AccessorEvent)); - view_dispatcher = view_dispatcher_alloc(); - auto callback = cbc::obtain_connector(this, &AccessorAppViewManager::previous_view_callback); + view_holder = view_holder_alloc(); + auto callback = + cbc::obtain_connector(this, &AccessorAppViewManager::view_holder_back_callback); // allocate views submenu = submenu_alloc(); - add_view(ViewType::Submenu, submenu_get_view(submenu)); - popup = popup_alloc(); - add_view(ViewType::Popup, popup_get_view(popup)); + + // set back callback + view_holder_set_back_callback(view_holder, callback, NULL); gui = static_cast(furi_record_open(RECORD_GUI)); - view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen); - - // set previous view callback for all views - view_set_previous_callback(submenu_get_view(submenu), callback); - view_set_previous_callback(popup_get_view(popup), callback); + view_holder_attach_to_gui(view_holder, gui); } AccessorAppViewManager::~AccessorAppViewManager() { - // remove views - view_dispatcher_remove_view( - view_dispatcher, static_cast(AccessorAppViewManager::ViewType::Submenu)); - view_dispatcher_remove_view( - view_dispatcher, static_cast(AccessorAppViewManager::ViewType::Popup)); - + // remove current view + view_holder_set_view(view_holder, NULL); // free view modules furi_record_close(RECORD_GUI); submenu_free(submenu); popup_free(popup); - - // free dispatcher - view_dispatcher_free(view_dispatcher); - + // free view holder + view_holder_free(view_holder); // free event queue furi_message_queue_free(event_queue); } void AccessorAppViewManager::switch_to(ViewType type) { - view_dispatcher_switch_to_view(view_dispatcher, static_cast(type)); + View* view; + + switch(type) { + case ViewType::Submenu: + view = submenu_get_view(submenu); + break; + case ViewType::Popup: + view = popup_get_view(popup); + break; + default: + furi_crash(); + } + + view_holder_set_view(view_holder, view); } Submenu* AccessorAppViewManager::get_submenu() { @@ -65,16 +69,10 @@ void AccessorAppViewManager::send_event(AccessorEvent* event) { furi_check(result == FuriStatusOk); } -uint32_t AccessorAppViewManager::previous_view_callback(void*) { +void AccessorAppViewManager::view_holder_back_callback(void*) { if(event_queue != NULL) { AccessorEvent event; event.type = AccessorEvent::Type::Back; send_event(&event); } - - return VIEW_IGNORE; -} - -void AccessorAppViewManager::add_view(ViewType view_type, View* view) { - view_dispatcher_add_view(view_dispatcher, static_cast(view_type), view); } diff --git a/applications/debug/accessor/accessor_view_manager.h b/applications/debug/accessor/accessor_view_manager.h index 66e54e41c..c0a12cbe8 100644 --- a/applications/debug/accessor/accessor_view_manager.h +++ b/applications/debug/accessor/accessor_view_manager.h @@ -1,6 +1,6 @@ #pragma once #include -#include +#include #include #include #include "accessor_event.h" @@ -10,7 +10,6 @@ public: enum class ViewType : uint8_t { Submenu, Popup, - Tune, }; FuriMessageQueue* event_queue; @@ -27,11 +26,10 @@ public: Popup* get_popup(void); private: - ViewDispatcher* view_dispatcher; Gui* gui; + ViewHolder* view_holder; - uint32_t previous_view_callback(void* context); - void add_view(ViewType view_type, View* view); + void view_holder_back_callback(void* context); // view elements Submenu* submenu; diff --git a/applications/debug/battery_test_app/battery_test_app.c b/applications/debug/battery_test_app/battery_test_app.c index 5f9934e77..363c8f4d5 100644 --- a/applications/debug/battery_test_app/battery_test_app.c +++ b/applications/debug/battery_test_app/battery_test_app.c @@ -42,7 +42,6 @@ BatteryTestApp* battery_test_alloc(void) { // View dispatcher app->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_enable_queue(app->view_dispatcher); view_dispatcher_set_event_callback_context(app->view_dispatcher, app); view_dispatcher_set_tick_event_callback( app->view_dispatcher, battery_test_battery_info_update_model, 500); diff --git a/applications/debug/bt_debug_app/bt_debug_app.c b/applications/debug/bt_debug_app/bt_debug_app.c index 109feee60..56c67e3e6 100644 --- a/applications/debug/bt_debug_app/bt_debug_app.c +++ b/applications/debug/bt_debug_app/bt_debug_app.c @@ -36,7 +36,6 @@ BtDebugApp* bt_debug_app_alloc(void) { // View dispatcher app->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_enable_queue(app->view_dispatcher); view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); // Views diff --git a/applications/debug/crash_test/crash_test.c b/applications/debug/crash_test/crash_test.c index ae0074fe1..2b2be13d6 100644 --- a/applications/debug/crash_test/crash_test.c +++ b/applications/debug/crash_test/crash_test.c @@ -66,7 +66,6 @@ CrashTest* crash_test_alloc(void) { instance->gui = furi_record_open(RECORD_GUI); instance->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_enable_queue(instance->view_dispatcher); view_dispatcher_attach_to_gui( instance->view_dispatcher, instance->gui, ViewDispatcherTypeFullscreen); diff --git a/applications/debug/display_test/display_test.c b/applications/debug/display_test/display_test.c index 3028a13b9..3b742906d 100644 --- a/applications/debug/display_test/display_test.c +++ b/applications/debug/display_test/display_test.c @@ -126,7 +126,6 @@ DisplayTest* display_test_alloc(void) { instance->gui = furi_record_open(RECORD_GUI); instance->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_enable_queue(instance->view_dispatcher); view_dispatcher_attach_to_gui( instance->view_dispatcher, instance->gui, ViewDispatcherTypeFullscreen); diff --git a/applications/debug/event_loop_blink_test/event_loop_blink_test.c b/applications/debug/event_loop_blink_test/event_loop_blink_test.c index 5c7e0ce55..7f00e63f2 100644 --- a/applications/debug/event_loop_blink_test/event_loop_blink_test.c +++ b/applications/debug/event_loop_blink_test/event_loop_blink_test.c @@ -82,7 +82,8 @@ static void view_port_input_callback(InputEvent* input_event, void* context) { furi_message_queue_put(app->input_queue, input_event, 0); } -static bool input_queue_callback(FuriMessageQueue* queue, void* context) { +static bool input_queue_callback(FuriEventLoopObject* object, void* context) { + FuriMessageQueue* queue = object; EventLoopBlinkTestApp* app = context; InputEvent event; @@ -144,7 +145,7 @@ int32_t event_loop_blink_test_app(void* arg) { gui_add_view_port(gui, view_port, GuiLayerFullscreen); furi_event_loop_tick_set(app.event_loop, 500, event_loop_tick_callback, &app); - furi_event_loop_message_queue_subscribe( + furi_event_loop_subscribe_message_queue( app.event_loop, app.input_queue, FuriEventLoopEventIn, input_queue_callback, &app); furi_event_loop_run(app.event_loop); @@ -154,7 +155,7 @@ int32_t event_loop_blink_test_app(void* arg) { furi_record_close(RECORD_GUI); - furi_event_loop_message_queue_unsubscribe(app.event_loop, app.input_queue); + furi_event_loop_unsubscribe(app.event_loop, app.input_queue); furi_message_queue_free(app.input_queue); for(size_t i = 0; i < TIMER_COUNT; ++i) { diff --git a/applications/debug/file_browser_test/file_browser_app.c b/applications/debug/file_browser_test/file_browser_app.c index 60ddf1b68..89b8b9274 100644 --- a/applications/debug/file_browser_test/file_browser_app.c +++ b/applications/debug/file_browser_test/file_browser_app.c @@ -33,8 +33,6 @@ FileBrowserApp* file_browser_app_alloc(char* arg) { app->dialogs = furi_record_open(RECORD_DIALOGS); app->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_enable_queue(app->view_dispatcher); - app->scene_manager = scene_manager_alloc(&file_browser_scene_handlers, app); view_dispatcher_set_event_callback_context(app->view_dispatcher, app); diff --git a/applications/debug/file_browser_test/icons/badkb_10px.png b/applications/debug/file_browser_test/icons/badkb_10px.png index 037474aa3..2b5a3bf97 100644 Binary files a/applications/debug/file_browser_test/icons/badkb_10px.png and b/applications/debug/file_browser_test/icons/badkb_10px.png differ diff --git a/applications/debug/file_browser_test/scenes/file_browser_scene_start.c b/applications/debug/file_browser_test/scenes/file_browser_scene_start.c index 1f2ccddad..912b50419 100644 --- a/applications/debug/file_browser_test/scenes/file_browser_scene_start.c +++ b/applications/debug/file_browser_test/scenes/file_browser_scene_start.c @@ -19,7 +19,7 @@ bool file_browser_scene_start_on_event(void* context, SceneManagerEvent event) { bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { - furi_string_set(app->file_path, ANY_PATH("badusb/Demos/demo_windows.txt")); + furi_string_set(app->file_path, EXT_PATH("badusb/Demos/demo_windows.txt")); scene_manager_next_scene(app->scene_manager, FileBrowserSceneBrowser); consumed = true; } else if(event.type == SceneManagerEventTypeTick) { diff --git a/applications/debug/infrared_test/application.fam b/applications/debug/infrared_test/application.fam new file mode 100644 index 000000000..bfd7cd5d4 --- /dev/null +++ b/applications/debug/infrared_test/application.fam @@ -0,0 +1,8 @@ +App( + appid="infrared_test", + name="Infrared Test", + apptype=FlipperAppType.DEBUG, + entry_point="infrared_test_app", + fap_category="Debug", + targets=["f7"], +) diff --git a/applications/debug/infrared_test/infrared_test.c b/applications/debug/infrared_test/infrared_test.c new file mode 100644 index 000000000..0187bd49d --- /dev/null +++ b/applications/debug/infrared_test/infrared_test.c @@ -0,0 +1,61 @@ +#include +#include + +#define TAG "InfraredTest" + +#define CARRIER_FREQ_HZ (38000UL) +#define CARRIER_DUTY (0.33f) + +#define BURST_DURATION_US (600UL) +#define BURST_COUNT (50UL) + +typedef struct { + bool level; + uint32_t count; +} InfraredTestApp; + +static FuriHalInfraredTxGetDataState + infrared_test_app_tx_data_callback(void* context, uint32_t* duration, bool* level) { + furi_assert(context); + furi_assert(duration); + furi_assert(level); + + InfraredTestApp* app = context; + + *duration = BURST_DURATION_US; + *level = app->level; + + app->level = !app->level; + app->count += 1; + + if(app->count < BURST_COUNT * 2) { + return FuriHalInfraredTxGetDataStateOk; + } else { + return FuriHalInfraredTxGetDataStateLastDone; + } +} + +int32_t infrared_test_app(void* arg) { + UNUSED(arg); + + InfraredTestApp app = { + .level = true, + }; + + FURI_LOG_I(TAG, "Starting test signal on PA7"); + + furi_hal_infrared_set_tx_output(FuriHalInfraredTxPinExtPA7); + furi_hal_infrared_async_tx_set_data_isr_callback(infrared_test_app_tx_data_callback, &app); + furi_hal_infrared_async_tx_start(CARRIER_FREQ_HZ, CARRIER_DUTY); + furi_hal_infrared_async_tx_wait_termination(); + furi_hal_infrared_set_tx_output(FuriHalInfraredTxPinInternal); + + FURI_LOG_I(TAG, "Test signal end"); + FURI_LOG_I( + TAG, + "The measured signal should be %luus +-%.1fus", + (app.count - 1) * BURST_DURATION_US, + (double)1000000.0 / CARRIER_FREQ_HZ); + + return 0; +} diff --git a/applications/debug/lfrfid_debug/lfrfid_debug.c b/applications/debug/lfrfid_debug/lfrfid_debug.c index 13c0b299f..962afd1c3 100644 --- a/applications/debug/lfrfid_debug/lfrfid_debug.c +++ b/applications/debug/lfrfid_debug/lfrfid_debug.c @@ -17,7 +17,6 @@ static LfRfidDebug* lfrfid_debug_alloc(void) { app->view_dispatcher = view_dispatcher_alloc(); app->scene_manager = scene_manager_alloc(&lfrfid_debug_scene_handlers, app); - view_dispatcher_enable_queue(app->view_dispatcher); view_dispatcher_set_event_callback_context(app->view_dispatcher, app); view_dispatcher_set_custom_event_callback( app->view_dispatcher, lfrfid_debug_custom_event_callback); diff --git a/applications/debug/locale_test/locale_test.c b/applications/debug/locale_test/locale_test.c index 1ca077db1..51d45a6b0 100644 --- a/applications/debug/locale_test/locale_test.c +++ b/applications/debug/locale_test/locale_test.c @@ -61,7 +61,6 @@ static LocaleTestApp* locale_test_alloc(void) { // View dispatcher app->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_enable_queue(app->view_dispatcher); view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); // Views diff --git a/applications/debug/rpc_debug_app/rpc_debug_app.c b/applications/debug/rpc_debug_app/rpc_debug_app.c index 5e53c221e..1536b8918 100644 --- a/applications/debug/rpc_debug_app/rpc_debug_app.c +++ b/applications/debug/rpc_debug_app/rpc_debug_app.c @@ -99,7 +99,6 @@ static RpcDebugApp* rpc_debug_app_alloc(void) { view_dispatcher_set_tick_event_callback( app->view_dispatcher, rpc_debug_app_tick_event_callback, 100); view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - view_dispatcher_enable_queue(app->view_dispatcher); app->widget = widget_alloc(); view_dispatcher_add_view( diff --git a/applications/debug/subghz_test/images/DolphinCommon_56x48.png b/applications/debug/subghz_test/images/DolphinCommon_56x48.png index 089aaed83..9cdc2e448 100644 Binary files a/applications/debug/subghz_test/images/DolphinCommon_56x48.png and b/applications/debug/subghz_test/images/DolphinCommon_56x48.png differ diff --git a/applications/debug/subghz_test/subghz_test_10px.png b/applications/debug/subghz_test/subghz_test_10px.png index 10dac0eca..77dc6d382 100644 Binary files a/applications/debug/subghz_test/subghz_test_10px.png and b/applications/debug/subghz_test/subghz_test_10px.png differ diff --git a/applications/debug/subghz_test/subghz_test_app.c b/applications/debug/subghz_test/subghz_test_app.c index 6eba864f6..dccdac213 100644 --- a/applications/debug/subghz_test/subghz_test_app.c +++ b/applications/debug/subghz_test/subghz_test_app.c @@ -30,7 +30,6 @@ SubGhzTestApp* subghz_test_app_alloc(void) { // View Dispatcher app->view_dispatcher = view_dispatcher_alloc(); app->scene_manager = scene_manager_alloc(&subghz_test_scene_handlers, app); - view_dispatcher_enable_queue(app->view_dispatcher); view_dispatcher_set_event_callback_context(app->view_dispatcher, app); view_dispatcher_set_custom_event_callback( diff --git a/applications/debug/text_box_view_test/text_box_view_test.c b/applications/debug/text_box_view_test/text_box_view_test.c index 7bbcb285b..4d63e3779 100644 --- a/applications/debug/text_box_view_test/text_box_view_test.c +++ b/applications/debug/text_box_view_test/text_box_view_test.c @@ -126,7 +126,6 @@ int32_t text_box_view_test_app(void* p) { Gui* gui = furi_record_open(RECORD_GUI); ViewDispatcher* view_dispatcher = view_dispatcher_alloc(); view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen); - view_dispatcher_enable_queue(view_dispatcher); TextBoxViewTest instance = { .text_box = text_box_alloc(), diff --git a/applications/debug/uart_echo/uart_echo.c b/applications/debug/uart_echo/uart_echo.c index 8e1884e9a..bf38ba4c2 100644 --- a/applications/debug/uart_echo/uart_echo.c +++ b/applications/debug/uart_echo/uart_echo.c @@ -242,7 +242,6 @@ static UartEchoApp* uart_echo_app_alloc(uint32_t baudrate) { // View dispatcher app->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_enable_queue(app->view_dispatcher); view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); // Views diff --git a/applications/debug/unit_tests/resources/unit_tests/subghz/dickert_mahs.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/dickert_mahs.sub new file mode 100644 index 000000000..9737b71a6 --- /dev/null +++ b/applications/debug/unit_tests/resources/unit_tests/subghz/dickert_mahs.sub @@ -0,0 +1,7 @@ +Filetype: Flipper SubGhz Key File +Version: 1 +Frequency: 433920000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: Dickert_MAHS +Bit: 36 +Key: 00 00 00 01 55 57 55 15 diff --git a/applications/debug/unit_tests/resources/unit_tests/subghz/dickert_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/dickert_raw.sub new file mode 100644 index 000000000..544fc7a1d --- /dev/null +++ b/applications/debug/unit_tests/resources/unit_tests/subghz/dickert_raw.sub @@ -0,0 +1,7 @@ +Filetype: Flipper SubGhz RAW File +Version: 1 +Frequency: 433920000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: RAW +RAW_Data: 112254 -62882 64 -8912 798 -844 416 -418 806 -850 396 -45206 440 -428 794 -442 804 -422 822 -810 414 -414 824 -832 412 -416 808 -848 376 -446 792 -846 382 -448 816 -828 410 -416 810 -844 382 -416 834 -818 410 -414 810 -856 408 -810 412 -836 384 -442 808 -814 402 -844 414 -834 378 -436 808 -844 396 -422 798 -844 416 -416 814 -404 812 -440 810 -842 396 -422 798 -840 414 -414 806 -850 398 -45210 450 -420 796 -436 780 -446 802 -848 380 -434 806 -846 400 -422 800 -840 410 -408 836 -812 414 -410 826 -840 378 -440 804 -848 396 -426 812 -810 426 -394 826 -844 414 -810 420 -834 378 -442 808 -832 412 -812 416 -830 410 -406 810 -844 400 -420 832 -810 414 -416 800 -446 798 -440 812 -808 426 -410 800 -836 412 -414 806 -836 412 -45216 450 -420 798 -434 806 -414 802 -846 382 -438 814 -832 410 -410 838 -834 396 -430 810 -842 394 -392 826 -840 414 -414 802 -850 396 -428 812 -842 394 -394 828 -842 414 -810 424 -812 392 -434 812 -844 398 -848 380 -844 408 -416 820 -810 414 -406 816 -836 412 -416 836 -414 816 -398 816 -840 420 -410 802 -844 416 -416 804 -824 410 -45232 446 -400 802 -442 810 -432 804 -842 396 -392 826 -842 410 -410 834 -818 378 -442 804 -854 406 -408 806 -838 408 -428 804 -844 396 -392 826 -840 410 -410 834 -810 414 -832 408 -834 380 -440 802 -826 410 -836 412 -838 396 -424 796 -842 414 -414 804 -848 396 -426 812 -412 814 -414 824 -832 410 -416 806 -848 382 -420 834 -814 422 -45228 416 -422 802 -446 810 -420 790 -846 382 -448 818 -828 408 -416 808 -848 382 -418 830 -816 410 -412 812 -856 410 -382 834 -846 382 -418 832 -818 408 -412 812 -856 408 -814 414 -838 396 -428 810 -808 424 -836 380 -844 404 -416 802 -840 424 -394 826 -840 414 -382 836 -412 822 -436 812 -806 424 -394 826 -844 416 -382 838 -816 402 -45228 438 -430 796 -444 806 -424 822 -810 412 -416 822 -832 412 -416 804 -844 408 -414 824 -812 412 -408 812 -834 410 -414 804 -848 408 -412 802 -840 424 -412 802 -834 412 -842 384 -848 396 -426 814 -808 424 -816 392 -866 382 -414 838 -816 414 -428 792 -846 380 -440 810 -438 812 -412 802 -846 380 -438 826 -840 380 -416 838 -814 404 -45226 450 -404 820 -408 806 -452 792 -848 382 -440 814 -832 410 -416 810 -846 378 -450 792 -846 380 -446 816 -830 410 -386 836 -846 376 -410 828 -846 380 -446 814 -828 410 -814 414 -836 396 -428 810 -842 394 -816 410 -836 406 -430 812 -810 426 -394 826 -838 +RAW_Data: 414 -414 808 -416 826 -438 814 -816 420 -414 834 -814 418 -418 808 -848 398 -45218 412 -438 824 -412 812 -418 832 -852 378 -446 782 -862 410 -386 838 -848 384 -420 836 -820 418 -414 814 -854 408 -388 838 -814 418 -422 836 -816 394 -434 812 -846 398 -850 380 -848 410 -418 822 -812 416 -850 368 -854 412 -418 810 -850 384 -422 834 -820 416 -414 812 -428 836 -412 804 -848 382 -450 818 -828 412 -418 808 -850 380 -45228 452 -420 798 -434 806 -416 834 -818 384 -440 810 -820 404 -420 834 -814 416 -418 834 -824 386 -442 810 -818 404 -420 834 -814 416 -418 834 -820 410 -414 810 -850 406 -812 414 -816 404 -420 818 -838 386 -848 394 -828 414 -414 838 -814 406 -420 820 -842 384 -446 794 -438 810 -412 802 -848 394 -432 812 -842 394 -392 830 -842 414 -105578 64 -1760 130 -196 130 -832 160 -128 62 -1278 194 -1316 230 -96 362 -64 64 -398 diff --git a/applications/debug/unit_tests/tests/furi/furi_event_loop.c b/applications/debug/unit_tests/tests/furi/furi_event_loop.c index 4eeecb2b8..291181c77 100644 --- a/applications/debug/unit_tests/tests/furi/furi_event_loop.c +++ b/applications/debug/unit_tests/tests/furi/furi_event_loop.c @@ -19,25 +19,24 @@ typedef struct { uint32_t consumer_counter; } TestFuriData; -bool test_furi_event_loop_producer_mq_callback(FuriMessageQueue* queue, void* context) { +bool test_furi_event_loop_producer_mq_callback(FuriEventLoopObject* object, void* context) { furi_check(context); TestFuriData* data = context; - furi_check(data->mq == queue, "Invalid queue"); + furi_check(data->mq == object, "Invalid queue"); FURI_LOG_I( TAG, "producer_mq_callback: %lu %lu", data->producer_counter, data->consumer_counter); - // Remove and add should not cause crash - // if(data->producer_counter == EVENT_LOOP_EVENT_COUNT/2) { - // furi_event_loop_message_queue_remove(data->producer_event_loop, data->mq); - // furi_event_loop_message_queue_add( - // data->producer_event_loop, - // data->mq, - // FuriEventLoopEventOut, - // test_furi_event_loop_producer_mq_callback, - // data); - // } + if(data->producer_counter == EVENT_LOOP_EVENT_COUNT / 2) { + furi_event_loop_unsubscribe(data->producer_event_loop, data->mq); + furi_event_loop_subscribe_message_queue( + data->producer_event_loop, + data->mq, + FuriEventLoopEventOut, + test_furi_event_loop_producer_mq_callback, + data); + } if(data->producer_counter == EVENT_LOOP_EVENT_COUNT) { furi_event_loop_stop(data->producer_event_loop); @@ -61,7 +60,7 @@ int32_t test_furi_event_loop_producer(void* p) { FURI_LOG_I(TAG, "producer start 1st run"); data->producer_event_loop = furi_event_loop_alloc(); - furi_event_loop_message_queue_subscribe( + furi_event_loop_subscribe_message_queue( data->producer_event_loop, data->mq, FuriEventLoopEventOut, @@ -73,7 +72,7 @@ int32_t test_furi_event_loop_producer(void* p) { // 2 EventLoop index, 0xFFFFFFFF - all possible flags, emulate uncleared flags xTaskNotifyIndexed(xTaskGetCurrentTaskHandle(), 2, 0xFFFFFFFF, eSetBits); - furi_event_loop_message_queue_unsubscribe(data->producer_event_loop, data->mq); + furi_event_loop_unsubscribe(data->producer_event_loop, data->mq); furi_event_loop_free(data->producer_event_loop); FURI_LOG_I(TAG, "producer start 2nd run"); @@ -81,7 +80,7 @@ int32_t test_furi_event_loop_producer(void* p) { data->producer_counter = 0; data->producer_event_loop = furi_event_loop_alloc(); - furi_event_loop_message_queue_subscribe( + furi_event_loop_subscribe_message_queue( data->producer_event_loop, data->mq, FuriEventLoopEventOut, @@ -90,7 +89,7 @@ int32_t test_furi_event_loop_producer(void* p) { furi_event_loop_run(data->producer_event_loop); - furi_event_loop_message_queue_unsubscribe(data->producer_event_loop, data->mq); + furi_event_loop_unsubscribe(data->producer_event_loop, data->mq); furi_event_loop_free(data->producer_event_loop); FURI_LOG_I(TAG, "producer end"); @@ -98,11 +97,11 @@ int32_t test_furi_event_loop_producer(void* p) { return 0; } -bool test_furi_event_loop_consumer_mq_callback(FuriMessageQueue* queue, void* context) { +bool test_furi_event_loop_consumer_mq_callback(FuriEventLoopObject* object, void* context) { furi_check(context); TestFuriData* data = context; - furi_check(data->mq == queue); + furi_check(data->mq == object); furi_delay_us(furi_hal_random_get() % 1000); furi_check(furi_message_queue_get(data->mq, &data->consumer_counter, 0) == FuriStatusOk); @@ -110,16 +109,15 @@ bool test_furi_event_loop_consumer_mq_callback(FuriMessageQueue* queue, void* co FURI_LOG_I( TAG, "consumer_mq_callback: %lu %lu", data->producer_counter, data->consumer_counter); - // Remove and add should not cause crash - // if(data->producer_counter == EVENT_LOOP_EVENT_COUNT/2) { - // furi_event_loop_message_queue_remove(data->consumer_event_loop, data->mq); - // furi_event_loop_message_queue_add( - // data->consumer_event_loop, - // data->mq, - // FuriEventLoopEventIn, - // test_furi_event_loop_producer_mq_callback, - // data); - // } + if(data->consumer_counter == EVENT_LOOP_EVENT_COUNT / 2) { + furi_event_loop_unsubscribe(data->consumer_event_loop, data->mq); + furi_event_loop_subscribe_message_queue( + data->consumer_event_loop, + data->mq, + FuriEventLoopEventIn, + test_furi_event_loop_consumer_mq_callback, + data); + } if(data->consumer_counter == EVENT_LOOP_EVENT_COUNT) { furi_event_loop_stop(data->consumer_event_loop); @@ -137,7 +135,7 @@ int32_t test_furi_event_loop_consumer(void* p) { FURI_LOG_I(TAG, "consumer start 1st run"); data->consumer_event_loop = furi_event_loop_alloc(); - furi_event_loop_message_queue_subscribe( + furi_event_loop_subscribe_message_queue( data->consumer_event_loop, data->mq, FuriEventLoopEventIn, @@ -149,14 +147,14 @@ int32_t test_furi_event_loop_consumer(void* p) { // 2 EventLoop index, 0xFFFFFFFF - all possible flags, emulate uncleared flags xTaskNotifyIndexed(xTaskGetCurrentTaskHandle(), 2, 0xFFFFFFFF, eSetBits); - furi_event_loop_message_queue_unsubscribe(data->consumer_event_loop, data->mq); + furi_event_loop_unsubscribe(data->consumer_event_loop, data->mq); furi_event_loop_free(data->consumer_event_loop); FURI_LOG_I(TAG, "consumer start 2nd run"); data->consumer_counter = 0; data->consumer_event_loop = furi_event_loop_alloc(); - furi_event_loop_message_queue_subscribe( + furi_event_loop_subscribe_message_queue( data->consumer_event_loop, data->mq, FuriEventLoopEventIn, @@ -165,7 +163,7 @@ int32_t test_furi_event_loop_consumer(void* p) { furi_event_loop_run(data->consumer_event_loop); - furi_event_loop_message_queue_unsubscribe(data->consumer_event_loop, data->mq); + furi_event_loop_unsubscribe(data->consumer_event_loop, data->mq); furi_event_loop_free(data->consumer_event_loop); FURI_LOG_I(TAG, "consumer end"); diff --git a/applications/debug/unit_tests/tests/rpc/rpc_test.c b/applications/debug/unit_tests/tests/rpc/rpc_test.c index ef3e57091..55339d495 100644 --- a/applications/debug/unit_tests/tests/rpc/rpc_test.c +++ b/applications/debug/unit_tests/tests/rpc/rpc_test.c @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -35,8 +36,8 @@ static uint32_t command_id = 0; typedef struct { RpcSession* session; FuriStreamBuffer* output_stream; - FuriSemaphore* close_session_semaphore; - FuriSemaphore* terminate_semaphore; + FuriApiLock session_close_lock; + FuriApiLock session_terminate_lock; uint32_t timeout; } RpcSessionContext; @@ -92,8 +93,8 @@ static void test_rpc_setup(void) { rpc_session[0].output_stream = furi_stream_buffer_alloc(4096, 1); rpc_session_set_send_bytes_callback(rpc_session[0].session, output_bytes_callback); - rpc_session[0].close_session_semaphore = furi_semaphore_alloc(1, 0); - rpc_session[0].terminate_semaphore = furi_semaphore_alloc(1, 0); + rpc_session[0].session_close_lock = api_lock_alloc_locked(); + rpc_session[0].session_terminate_lock = api_lock_alloc_locked(); rpc_session_set_close_callback(rpc_session[0].session, test_rpc_session_close_callback); rpc_session_set_terminated_callback( rpc_session[0].session, test_rpc_session_terminated_callback); @@ -112,8 +113,8 @@ static void test_rpc_setup_second_session(void) { rpc_session[1].output_stream = furi_stream_buffer_alloc(1000, 1); rpc_session_set_send_bytes_callback(rpc_session[1].session, output_bytes_callback); - rpc_session[1].close_session_semaphore = furi_semaphore_alloc(1, 0); - rpc_session[1].terminate_semaphore = furi_semaphore_alloc(1, 0); + rpc_session[1].session_close_lock = api_lock_alloc_locked(); + rpc_session[1].session_terminate_lock = api_lock_alloc_locked(); rpc_session_set_close_callback(rpc_session[1].session, test_rpc_session_close_callback); rpc_session_set_terminated_callback( rpc_session[1].session, test_rpc_session_terminated_callback); @@ -121,36 +122,32 @@ static void test_rpc_setup_second_session(void) { } static void test_rpc_teardown(void) { - furi_check(rpc_session[0].close_session_semaphore); - furi_semaphore_acquire(rpc_session[0].terminate_semaphore, 0); + furi_check(rpc_session[0].session_close_lock); + api_lock_relock(rpc_session[0].session_terminate_lock); rpc_session_close(rpc_session[0].session); - furi_check( - furi_semaphore_acquire(rpc_session[0].terminate_semaphore, FuriWaitForever) == - FuriStatusOk); + api_lock_wait_unlock(rpc_session[0].session_terminate_lock); furi_record_close(RECORD_RPC); furi_stream_buffer_free(rpc_session[0].output_stream); - furi_semaphore_free(rpc_session[0].close_session_semaphore); - furi_semaphore_free(rpc_session[0].terminate_semaphore); + api_lock_free(rpc_session[0].session_close_lock); + api_lock_free(rpc_session[0].session_terminate_lock); ++command_id; rpc_session[0].output_stream = NULL; - rpc_session[0].close_session_semaphore = NULL; + rpc_session[0].session_close_lock = NULL; rpc = NULL; rpc_session[0].session = NULL; } static void test_rpc_teardown_second_session(void) { - furi_check(rpc_session[1].close_session_semaphore); - furi_semaphore_acquire(rpc_session[1].terminate_semaphore, 0); + furi_check(rpc_session[1].session_close_lock); + api_lock_relock(rpc_session[1].session_terminate_lock); rpc_session_close(rpc_session[1].session); - furi_check( - furi_semaphore_acquire(rpc_session[1].terminate_semaphore, FuriWaitForever) == - FuriStatusOk); + api_lock_wait_unlock(rpc_session[1].session_terminate_lock); furi_stream_buffer_free(rpc_session[1].output_stream); - furi_semaphore_free(rpc_session[1].close_session_semaphore); - furi_semaphore_free(rpc_session[1].terminate_semaphore); + api_lock_free(rpc_session[1].session_close_lock); + api_lock_free(rpc_session[1].session_terminate_lock); ++command_id; rpc_session[1].output_stream = NULL; - rpc_session[1].close_session_semaphore = NULL; + rpc_session[1].session_close_lock = NULL; rpc_session[1].session = NULL; } @@ -204,14 +201,14 @@ static void test_rpc_session_close_callback(void* context) { furi_check(context); RpcSessionContext* callbacks_context = context; - furi_check(furi_semaphore_release(callbacks_context->close_session_semaphore) == FuriStatusOk); + api_lock_unlock(callbacks_context->session_close_lock); } static void test_rpc_session_terminated_callback(void* context) { furi_check(context); RpcSessionContext* callbacks_context = context; - furi_check(furi_semaphore_release(callbacks_context->terminate_semaphore) == FuriStatusOk); + api_lock_unlock(callbacks_context->session_terminate_lock); } static void test_rpc_print_message_list(MsgList_t msg_list) { @@ -1645,7 +1642,7 @@ static void test_rpc_feed_rubbish_run( test_rpc_add_empty_to_list(expected, PB_CommandStatus_ERROR_DECODE, 0); - furi_check(furi_semaphore_acquire(rpc_session[0].close_session_semaphore, 0) != FuriStatusOk); + furi_check(api_lock_is_locked(rpc_session[0].session_close_lock)); test_rpc_encode_and_feed(input_before, 0); test_send_rubbish(rpc_session[0].session, pattern, pattern_size, size); test_rpc_encode_and_feed(input_after, 0); diff --git a/applications/debug/unit_tests/tests/subghz/subghz_test.c b/applications/debug/unit_tests/tests/subghz/subghz_test.c index f975ab1cd..68f83260e 100644 --- a/applications/debug/unit_tests/tests/subghz/subghz_test.c +++ b/applications/debug/unit_tests/tests/subghz/subghz_test.c @@ -663,6 +663,13 @@ MU_TEST(subghz_decoder_mastercode_test) { "Test decoder " SUBGHZ_PROTOCOL_MASTERCODE_NAME " error\r\n"); } +MU_TEST(subghz_decoder_dickert_test) { + mu_assert( + subghz_decoder_test( + EXT_PATH("unit_tests/subghz/dickert_raw.sub"), SUBGHZ_PROTOCOL_DICKERT_MAHS_NAME), + "Test decoder " SUBGHZ_PROTOCOL_DICKERT_MAHS_NAME " error\r\n"); +} + //test encoders MU_TEST(subghz_encoder_princeton_test) { mu_assert( @@ -827,6 +834,12 @@ MU_TEST(subghz_decoder_acurite_592txr_test) { "Test decoder " WS_PROTOCOL_ACURITE_592TXR_NAME " error\r\n"); } +MU_TEST(subghz_encoder_dickert_test) { + mu_assert( + subghz_encoder_test(EXT_PATH("unit_tests/subghz/dickert_mahs.sub")), + "Test encoder " SUBGHZ_PROTOCOL_DICKERT_MAHS_NAME " error\r\n"); +} + MU_TEST(subghz_random_test) { mu_assert(subghz_decode_random_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n"); } @@ -878,6 +891,7 @@ MU_TEST_SUITE(subghz) { MU_RUN_TEST(subghz_decoder_nice_one_test); MU_RUN_TEST(subghz_decoder_kinggates_stylo4k_test); MU_RUN_TEST(subghz_decoder_mastercode_test); + MU_RUN_TEST(subghz_decoder_dickert_test); MU_RUN_TEST(subghz_encoder_princeton_test); MU_RUN_TEST(subghz_encoder_came_test); @@ -906,6 +920,7 @@ MU_TEST_SUITE(subghz) { MU_RUN_TEST(subghz_encoder_dooya_test); MU_RUN_TEST(subghz_encoder_mastercode_test); MU_RUN_TEST(subghz_decoder_acurite_592txr_test); + MU_RUN_TEST(subghz_encoder_dickert_test); MU_RUN_TEST(subghz_random_test); subghz_test_deinit(); diff --git a/applications/debug/unit_tests/unit_test_api_table_i.h b/applications/debug/unit_tests/unit_test_api_table_i.h index 1adec4db2..50524e5b7 100644 --- a/applications/debug/unit_tests/unit_test_api_table_i.h +++ b/applications/debug/unit_tests/unit_test_api_table_i.h @@ -36,14 +36,10 @@ static constexpr auto unit_tests_api_table = sort(create_array_t( API_METHOD(furi_event_loop_alloc, FuriEventLoop*, (void)), API_METHOD(furi_event_loop_free, void, (FuriEventLoop*)), API_METHOD( - furi_event_loop_message_queue_subscribe, + furi_event_loop_subscribe_message_queue, void, - (FuriEventLoop*, - FuriMessageQueue*, - FuriEventLoopEvent, - FuriEventLoopMessageQueueCallback, - void*)), - API_METHOD(furi_event_loop_message_queue_unsubscribe, void, (FuriEventLoop*, FuriMessageQueue*)), + (FuriEventLoop*, FuriMessageQueue*, FuriEventLoopEvent, FuriEventLoopEventCallback, void*)), + API_METHOD(furi_event_loop_unsubscribe, void, (FuriEventLoop*, FuriEventLoopObject*)), API_METHOD(furi_event_loop_run, void, (FuriEventLoop*)), API_METHOD(furi_event_loop_stop, void, (FuriEventLoop*)), API_VARIABLE(PB_Main_msg, PB_Main_msg_t))); diff --git a/applications/debug/unit_tests/unit_tests.c b/applications/debug/unit_tests/unit_tests.c index 2b3468cbc..4e801e0b0 100644 --- a/applications/debug/unit_tests/unit_tests.c +++ b/applications/debug/unit_tests/unit_tests.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "test_runner.h" @@ -13,21 +14,14 @@ void unit_tests_cli(Cli* cli, FuriString* args, void* context) { test_runner_free(test_runner); } -static void unit_tests_pending(void* context, uint32_t arg) { - UNUSED(arg); - FuriThread* thread = context; - furi_thread_join(thread); - furi_thread_free(thread); -} - static int32_t unit_tests_thread(void* context) { + UNUSED(context); furi_delay_ms(5000); FuriString* args = furi_string_alloc(); TestRunner* test_runner = test_runner_alloc(NULL, args); test_runner_run(test_runner); test_runner_free(test_runner); furi_string_free(args); - furi_timer_pending_callback(unit_tests_pending, context, 0); return 0; } @@ -38,8 +32,6 @@ void unit_tests_on_system_start(void) { furi_record_close(RECORD_CLI); #endif if(furi_hal_is_normal_boot()) { - FuriThread* thread = furi_thread_alloc_ex("UnitTests", 4 * 1024, unit_tests_thread, NULL); - furi_thread_set_context(thread, thread); - furi_thread_start(thread); + run_parallel(unit_tests_thread, NULL, 4 * 1024); } } diff --git a/applications/debug/usb_test/usb_test.c b/applications/debug/usb_test/usb_test.c index ddec9d9b0..a71ac3c6e 100644 --- a/applications/debug/usb_test/usb_test.c +++ b/applications/debug/usb_test/usb_test.c @@ -63,7 +63,6 @@ UsbTestApp* usb_test_app_alloc(void) { // View dispatcher app->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_enable_queue(app->view_dispatcher); view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); // Views diff --git a/applications/examples/example_ble_beacon/ble_beacon_app.c b/applications/examples/example_ble_beacon/ble_beacon_app.c index faa3feb91..16979543c 100644 --- a/applications/examples/example_ble_beacon/ble_beacon_app.c +++ b/applications/examples/example_ble_beacon/ble_beacon_app.c @@ -75,7 +75,6 @@ static BleBeaconApp* ble_beacon_app_alloc(void) { view_dispatcher_set_tick_event_callback( app->view_dispatcher, ble_beacon_app_tick_event_callback, 100); view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - view_dispatcher_enable_queue(app->view_dispatcher); app->submenu = submenu_alloc(); view_dispatcher_add_view( diff --git a/applications/examples/example_ble_beacon/example_ble_beacon_10px.png b/applications/examples/example_ble_beacon/example_ble_beacon_10px.png index 7060e893d..c6aff4189 100644 Binary files a/applications/examples/example_ble_beacon/example_ble_beacon_10px.png and b/applications/examples/example_ble_beacon/example_ble_beacon_10px.png differ diff --git a/applications/examples/example_ble_beacon/images/lighthouse_35x44.png b/applications/examples/example_ble_beacon/images/lighthouse_35x44.png index 4cf4d19c5..8ca6d664d 100644 Binary files a/applications/examples/example_ble_beacon/images/lighthouse_35x44.png and b/applications/examples/example_ble_beacon/images/lighthouse_35x44.png differ diff --git a/applications/examples/example_event_loop/application.fam b/applications/examples/example_event_loop/application.fam new file mode 100644 index 000000000..a37ffb1a0 --- /dev/null +++ b/applications/examples/example_event_loop/application.fam @@ -0,0 +1,36 @@ +App( + appid="example_event_loop_timer", + name="Example: Event Loop Timer", + apptype=FlipperAppType.EXTERNAL, + sources=["example_event_loop_timer.c"], + entry_point="example_event_loop_timer_app", + fap_category="Examples", +) + +App( + appid="example_event_loop_mutex", + name="Example: Event Loop Mutex", + apptype=FlipperAppType.EXTERNAL, + sources=["example_event_loop_mutex.c"], + entry_point="example_event_loop_mutex_app", + fap_category="Examples", +) + +App( + appid="example_event_loop_stream_buffer", + name="Example: Event Loop Stream Buffer", + apptype=FlipperAppType.EXTERNAL, + sources=["example_event_loop_stream_buffer.c"], + entry_point="example_event_loop_stream_buffer_app", + fap_category="Examples", +) + +App( + appid="example_event_loop_multi", + name="Example: Event Loop Multi", + apptype=FlipperAppType.EXTERNAL, + sources=["example_event_loop_multi.c"], + entry_point="example_event_loop_multi_app", + requires=["gui"], + fap_category="Examples", +) diff --git a/applications/examples/example_event_loop/example_event_loop_multi.c b/applications/examples/example_event_loop/example_event_loop_multi.c new file mode 100644 index 000000000..ebfb00911 --- /dev/null +++ b/applications/examples/example_event_loop/example_event_loop_multi.c @@ -0,0 +1,342 @@ +/** + * @file example_event_loop_multi.c + * @brief Example application that demonstrates multiple primitives used with two FuriEventLoop instances. + * + * This application simulates a complex use case of having two concurrent event loops (each one executing in + * its own thread) using a stream buffer for communication and additional timers and message passing to handle + * the keypad input. Additionally, it shows how to use thread signals to stop an event loop in another thread. + * The GUI functionality is there only for the purpose of exclusive access to the input events. + * + * The application's functionality consists of the following: + * - Print keypad key names and types when pressed, + * - If the Back key is long-pressed, a countdown starts upon completion of which the app exits, + * - The countdown can be cancelled by long-pressing the Ok button, it also resets the counter, + * - Blocks of random data are periodically generated in a separate thread, + * - When ready, the main application thread gets notified and prints the data. + */ + +#include +#include +#include + +#include + +#define TAG "ExampleEventLoopMulti" + +#define COUNTDOWN_START_VALUE (5UL) +#define COUNTDOWN_INTERVAL_MS (1000UL) +#define WORKER_DATA_INTERVAL_MS (1500UL) + +#define INPUT_QUEUE_SIZE (8) +#define STREAM_BUFFER_SIZE (16) + +typedef struct { + FuriEventLoop* event_loop; + FuriEventLoopTimer* timer; + FuriStreamBuffer* stream_buffer; +} EventLoopMultiAppWorker; + +typedef struct { + Gui* gui; + ViewPort* view_port; + FuriThread* worker_thread; + FuriEventLoop* event_loop; + FuriMessageQueue* input_queue; + FuriEventLoopTimer* exit_timer; + FuriStreamBuffer* stream_buffer; + uint32_t exit_countdown_value; +} EventLoopMultiApp; + +/* + * Worker functions + */ + +// This function is executed each time the data is taken out of the stream buffer. It is used to restart the worker timer. +static bool + event_loop_multi_app_stream_buffer_worker_callback(FuriEventLoopObject* object, void* context) { + furi_assert(context); + EventLoopMultiAppWorker* worker = context; + + furi_assert(object == worker->stream_buffer); + + FURI_LOG_I(TAG, "Data was removed from buffer"); + // Restart the timer to generate another block of random data. + furi_event_loop_timer_start(worker->timer, WORKER_DATA_INTERVAL_MS); + + return true; +} + +// This function is executed when the worker timer expires. The timer will NOT restart automatically +// since it is of one-shot type. +static void event_loop_multi_app_worker_timer_callback(void* context) { + furi_assert(context); + EventLoopMultiAppWorker* worker = context; + + // Generate a block of random data. + uint8_t data[STREAM_BUFFER_SIZE]; + furi_hal_random_fill_buf(data, sizeof(data)); + // Put the generated data in the stream buffer. + // IMPORTANT: No waiting in the event handlers! + furi_check( + furi_stream_buffer_send(worker->stream_buffer, &data, sizeof(data), 0) == sizeof(data)); +} + +static EventLoopMultiAppWorker* + event_loop_multi_app_worker_alloc(FuriStreamBuffer* stream_buffer) { + EventLoopMultiAppWorker* worker = malloc(sizeof(EventLoopMultiAppWorker)); + // Create the worker event loop. + worker->event_loop = furi_event_loop_alloc(); + // Create the timer governing the data generation. + // It is of one-shot type, i.e. it will not restart automatically upon expiration. + worker->timer = furi_event_loop_timer_alloc( + worker->event_loop, + event_loop_multi_app_worker_timer_callback, + FuriEventLoopTimerTypeOnce, + worker); + + // Using the same stream buffer as the main thread (it was already created beforehand). + worker->stream_buffer = stream_buffer; + // Notify the worker event loop about data being taken out of the stream buffer. + furi_event_loop_subscribe_stream_buffer( + worker->event_loop, + worker->stream_buffer, + FuriEventLoopEventOut | FuriEventLoopEventFlagEdge, + event_loop_multi_app_stream_buffer_worker_callback, + worker); + + return worker; +} + +static void event_loop_multi_app_worker_free(EventLoopMultiAppWorker* worker) { + // IMPORTANT: The user code MUST unsubscribe from all events before deleting the event loop. + // Failure to do so will result in a crash. + furi_event_loop_unsubscribe(worker->event_loop, worker->stream_buffer); + // IMPORTANT: All timers MUST be deleted before deleting the associated event loop. + // Failure to do so will result in a crash. + furi_event_loop_timer_free(worker->timer); + // Now it is okay to delete the event loop. + furi_event_loop_free(worker->event_loop); + + free(worker); +} + +static void event_loop_multi_app_worker_run(EventLoopMultiAppWorker* worker) { + furi_event_loop_timer_start(worker->timer, WORKER_DATA_INTERVAL_MS); + furi_event_loop_run(worker->event_loop); +} + +// This function is the worker thread body and (obviously) is executed in the worker thread. +static int32_t event_loop_multi_app_worker_thread(void* context) { + furi_assert(context); + EventLoopMultiApp* app = context; + + // Because an event loop is used, it MUST be created in the thread it will be run in. + // Therefore, the worker creation and deletion is handled in the worker thread. + EventLoopMultiAppWorker* worker = event_loop_multi_app_worker_alloc(app->stream_buffer); + event_loop_multi_app_worker_run(worker); + event_loop_multi_app_worker_free(worker); + + return 0; +} + +/* + * Main application functions + */ + +// This function is executed in the GUI context each time an input event occurs (e.g. the user pressed a key) +static void event_loop_multi_app_input_callback(InputEvent* event, void* context) { + furi_assert(context); + EventLoopMultiApp* app = context; + // Pass the event to the the application's input queue + furi_check(furi_message_queue_put(app->input_queue, event, FuriWaitForever) == FuriStatusOk); +} + +// This function is executed each time new data is available in the stream buffer. +static bool + event_loop_multi_app_stream_buffer_callback(FuriEventLoopObject* object, void* context) { + furi_assert(context); + EventLoopMultiApp* app = context; + + furi_assert(object == app->stream_buffer); + // Get the data from the stream buffer + uint8_t data[STREAM_BUFFER_SIZE]; + // IMPORTANT: No waiting in the event handlers! + furi_check( + furi_stream_buffer_receive(app->stream_buffer, &data, sizeof(data), 0) == sizeof(data)); + + // Format the data for printing and print it to the debug output. + FuriString* tmp_str = furi_string_alloc(); + for(uint32_t i = 0; i < sizeof(data); ++i) { + furi_string_cat_printf(tmp_str, "%02X ", data[i]); + } + + FURI_LOG_I(TAG, "Received data: %s", furi_string_get_cstr(tmp_str)); + furi_string_free(tmp_str); + + return true; +} + +// This function is executed each time a new message is inserted in the input queue. +static bool event_loop_multi_app_input_queue_callback(FuriEventLoopObject* object, void* context) { + furi_assert(context); + EventLoopMultiApp* app = context; + + furi_assert(object == app->input_queue); + + InputEvent event; + // IMPORTANT: No waiting in the event handlers! + furi_check(furi_message_queue_get(app->input_queue, &event, 0) == FuriStatusOk); + + if(event.type == InputTypeLong) { + // The user has long-pressed the Back key, try starting the countdown. + if(event.key == InputKeyBack) { + if(!furi_event_loop_timer_is_running(app->exit_timer)) { + // Actually start the countdown + FURI_LOG_I(TAG, "Starting exit countdown!"); + furi_event_loop_timer_start(app->exit_timer, COUNTDOWN_INTERVAL_MS); + + } else { + // The countdown is already in progress, print a warning message + FURI_LOG_W(TAG, "Countdown has already been started"); + } + + // The user has long-pressed the Ok key, try stopping the countdown. + } else if(event.key == InputKeyOk) { + if(furi_event_loop_timer_is_running(app->exit_timer)) { + // Actually cancel the countdown + FURI_LOG_I(TAG, "Exit countdown cancelled!"); + app->exit_countdown_value = COUNTDOWN_START_VALUE; + furi_event_loop_timer_stop(app->exit_timer); + + } else { + // The countdown is not running, print a warning message + FURI_LOG_W(TAG, "Countdown has not been started yet"); + } + + } else { + // Not a Back or Ok key, just print its name. + FURI_LOG_I(TAG, "Long press: %s", input_get_key_name(event.key)); + } + + } else if(event.type == InputTypeShort) { + // Not a long press, just print the key's name. + FURI_LOG_I(TAG, "Short press: %s", input_get_key_name(event.key)); + } + + return true; +} + +// This function is executed each time the countdown timer expires. +static void event_loop_multi_app_exit_timer_callback(void* context) { + furi_assert(context); + EventLoopMultiApp* app = context; + + FURI_LOG_I(TAG, "Exiting in %lu ...", app->exit_countdown_value); + + // If the coundown value has reached 0, exit the application + if(app->exit_countdown_value == 0) { + FURI_LOG_I(TAG, "Exiting NOW!"); + + // Send a signal to the worker thread to exit. + // A signal handler that handles FuriSignalExit is already set by default. + furi_thread_signal(app->worker_thread, FuriSignalExit, NULL); + // Request the application event loop to stop. + furi_event_loop_stop(app->event_loop); + + // Otherwise just decrement it and wait for the next time the timer expires. + } else { + app->exit_countdown_value -= 1; + } +} + +static EventLoopMultiApp* event_loop_multi_app_alloc(void) { + EventLoopMultiApp* app = malloc(sizeof(EventLoopMultiApp)); + // Create event loop instances. + app->event_loop = furi_event_loop_alloc(); + + // Create a worker thread instance. The worker event loop will execute inside it. + app->worker_thread = furi_thread_alloc_ex( + "EventLoopMultiWorker", 1024, event_loop_multi_app_worker_thread, app); + // Create a message queue to receive the input events. + app->input_queue = furi_message_queue_alloc(INPUT_QUEUE_SIZE, sizeof(InputEvent)); + // Create a stream buffer to receive the generated data. + app->stream_buffer = furi_stream_buffer_alloc(STREAM_BUFFER_SIZE, STREAM_BUFFER_SIZE); + // Create a timer to run the countdown. + app->exit_timer = furi_event_loop_timer_alloc( + app->event_loop, + event_loop_multi_app_exit_timer_callback, + FuriEventLoopTimerTypePeriodic, + app); + + app->gui = furi_record_open(RECORD_GUI); + app->view_port = view_port_alloc(); + // Start the countdown from this value + app->exit_countdown_value = COUNTDOWN_START_VALUE; + // Gain exclusive access to the input events + view_port_input_callback_set(app->view_port, event_loop_multi_app_input_callback, app); + gui_add_view_port(app->gui, app->view_port, GuiLayerFullscreen); + // Notify the event loop about incoming messages in the queue + furi_event_loop_subscribe_message_queue( + app->event_loop, + app->input_queue, + FuriEventLoopEventIn, + event_loop_multi_app_input_queue_callback, + app); + // Notify the event loop about new data in the stream buffer + furi_event_loop_subscribe_stream_buffer( + app->event_loop, + app->stream_buffer, + FuriEventLoopEventIn | FuriEventLoopEventFlagEdge, + event_loop_multi_app_stream_buffer_callback, + app); + + return app; +} + +static void event_loop_multi_app_free(EventLoopMultiApp* app) { + gui_remove_view_port(app->gui, app->view_port); + furi_record_close(RECORD_GUI); + // IMPORTANT: The user code MUST unsubscribe from all events before deleting the event loop. + // Failure to do so will result in a crash. + furi_event_loop_unsubscribe(app->event_loop, app->input_queue); + furi_event_loop_unsubscribe(app->event_loop, app->stream_buffer); + // Delete all instances + view_port_free(app->view_port); + furi_message_queue_free(app->input_queue); + furi_stream_buffer_free(app->stream_buffer); + // IMPORTANT: All timers MUST be deleted before deleting the associated event loop. + // Failure to do so will result in a crash. + furi_event_loop_timer_free(app->exit_timer); + furi_thread_free(app->worker_thread); + furi_event_loop_free(app->event_loop); + + free(app); +} + +static void event_loop_multi_app_run(EventLoopMultiApp* app) { + FURI_LOG_I(TAG, "Press keys to see them printed here."); + FURI_LOG_I(TAG, "Long press \"Back\" to exit after %lu seconds.", COUNTDOWN_START_VALUE); + FURI_LOG_I(TAG, "Long press \"Ok\" to cancel the countdown."); + + // Start the worker thread + furi_thread_start(app->worker_thread); + // Run the application event loop. This call will block until the application is about to exit. + furi_event_loop_run(app->event_loop); + // Wait for the worker thread to finish. + furi_thread_join(app->worker_thread); +} + +/******************************************************************* + * vvv START HERE vvv + * + * The application's entry point - referenced in application.fam + *******************************************************************/ +int32_t example_event_loop_multi_app(void* arg) { + UNUSED(arg); + + EventLoopMultiApp* app = event_loop_multi_app_alloc(); + event_loop_multi_app_run(app); + event_loop_multi_app_free(app); + + return 0; +} diff --git a/applications/examples/example_event_loop/example_event_loop_mutex.c b/applications/examples/example_event_loop/example_event_loop_mutex.c new file mode 100644 index 000000000..d043f3f89 --- /dev/null +++ b/applications/examples/example_event_loop/example_event_loop_mutex.c @@ -0,0 +1,140 @@ +/** + * @file example_event_loop_mutex.c + * @brief Example application that demonstrates the FuriEventLoop and FuriMutex integration. + * + * This application simulates a use case where a time-consuming blocking operation is executed + * in a separate thread and a mutex is being used for synchronization. The application runs 10 iterations + * of the above mentioned simulated work and prints the results to the debug output each time, then exits. + */ + +#include +#include + +#define TAG "ExampleEventLoopMutex" + +#define WORKER_ITERATION_COUNT (10) +// We are interested in IN events (for the mutex, that means that the mutex has been released), +// using edge trigger mode (reacting only to changes in mutex state) and +// employing one-shot mode to automatically unsubscribe before the event is processed. +#define MUTEX_EVENT_AND_FLAGS \ + (FuriEventLoopEventIn | FuriEventLoopEventFlagEdge | FuriEventLoopEventFlagOnce) + +typedef struct { + FuriEventLoop* event_loop; + FuriThread* worker_thread; + FuriMutex* worker_mutex; + uint8_t worker_result; +} EventLoopMutexApp; + +// This funciton is being run in a separate thread to simulate lenghty blocking operations +static int32_t event_loop_mutex_app_worker_thread(void* context) { + furi_assert(context); + EventLoopMutexApp* app = context; + + FURI_LOG_I(TAG, "Worker thread started"); + + // Run 10 iterations of simulated work + for(uint32_t i = 0; i < WORKER_ITERATION_COUNT; ++i) { + FURI_LOG_I(TAG, "Doing work ..."); + // Take the mutex so that no-one can access the worker_result variable + furi_check(furi_mutex_acquire(app->worker_mutex, FuriWaitForever) == FuriStatusOk); + // Simulate a blocking operation with a random delay between 900 and 1100 ms + const uint32_t work_time_ms = 900 + furi_hal_random_get() % 200; + furi_delay_ms(work_time_ms); + // Simulate a result with a random number between 0 and 255 + app->worker_result = furi_hal_random_get() % 0xFF; + + FURI_LOG_I(TAG, "Work done in %lu ms", work_time_ms); + // Release the mutex, which will notify the event loop that the result is ready + furi_check(furi_mutex_release(app->worker_mutex) == FuriStatusOk); + // Return control to the scheduler so that the event loop can take the mutex in its turn + furi_thread_yield(); + } + + FURI_LOG_I(TAG, "All work done, worker thread out!"); + // Request the event loop to stop + furi_event_loop_stop(app->event_loop); + + return 0; +} + +// This function is being run each time when the mutex gets released +static bool event_loop_mutex_app_event_callback(FuriEventLoopObject* object, void* context) { + furi_assert(context); + + EventLoopMutexApp* app = context; + furi_assert(object == app->worker_mutex); + + // Take the mutex so that no-one can access the worker_result variable + // IMPORTANT: the wait time MUST be 0, i.e. the event loop event callbacks + // must NOT ever block. If it is possible that the mutex will be taken by + // others, then the event callback code must take it into account. + furi_check(furi_mutex_acquire(app->worker_mutex, 0) == FuriStatusOk); + // Access the worker_result variable and print it. + FURI_LOG_I(TAG, "Result available! Value: %u", app->worker_result); + // Release the mutex, enabling the worker thread to continue when it's ready + furi_check(furi_mutex_release(app->worker_mutex) == FuriStatusOk); + // Subscribe for the mutex release events again, since we were unsubscribed automatically + // before processing the event. + furi_event_loop_subscribe_mutex( + app->event_loop, + app->worker_mutex, + MUTEX_EVENT_AND_FLAGS, + event_loop_mutex_app_event_callback, + app); + + return true; +} + +static EventLoopMutexApp* event_loop_mutex_app_alloc(void) { + EventLoopMutexApp* app = malloc(sizeof(EventLoopMutexApp)); + + // Create an event loop instance. + app->event_loop = furi_event_loop_alloc(); + // Create a worker thread instance. + app->worker_thread = furi_thread_alloc_ex( + "EventLoopMutexWorker", 1024, event_loop_mutex_app_worker_thread, app); + // Create a mutex instance. + app->worker_mutex = furi_mutex_alloc(FuriMutexTypeNormal); + // Subscribe for the mutex release events. + // Note that since FuriEventLoopEventFlagOneShot is used, we will be automatically unsubscribed + // from events before entering the event processing callback. This is necessary in order to not + // trigger on events caused by releasing the mutex in the callback. + furi_event_loop_subscribe_mutex( + app->event_loop, + app->worker_mutex, + MUTEX_EVENT_AND_FLAGS, + event_loop_mutex_app_event_callback, + app); + + return app; +} + +static void event_loop_mutex_app_free(EventLoopMutexApp* app) { + // IMPORTANT: The user code MUST unsubscribe from all events before deleting the event loop. + // Failure to do so will result in a crash. + furi_event_loop_unsubscribe(app->event_loop, app->worker_mutex); + // Delete all instances + furi_thread_free(app->worker_thread); + furi_mutex_free(app->worker_mutex); + furi_event_loop_free(app->event_loop); + + free(app); +} + +static void event_loop_mutex_app_run(EventLoopMutexApp* app) { + furi_thread_start(app->worker_thread); + furi_event_loop_run(app->event_loop); + furi_thread_join(app->worker_thread); +} + +// The application's entry point - referenced in application.fam +int32_t example_event_loop_mutex_app(void* arg) { + UNUSED(arg); + + EventLoopMutexApp* app = event_loop_mutex_app_alloc(); + event_loop_mutex_app_run(app); + event_loop_mutex_app_free(app); + + return 0; +} diff --git a/applications/examples/example_event_loop/example_event_loop_stream_buffer.c b/applications/examples/example_event_loop/example_event_loop_stream_buffer.c new file mode 100644 index 000000000..65dbd83cf --- /dev/null +++ b/applications/examples/example_event_loop/example_event_loop_stream_buffer.c @@ -0,0 +1,131 @@ +/** + * @file example_event_loop_stream_buffer.c + * @brief Example application that demonstrates the FuriEventLoop and FuriStreamBuffer integration. + * + * This application simulates a use case where some data data stream comes from a separate thread (or hardware) + * and a stream buffer is used to act as an intermediate buffer. The worker thread produces 10 iterations of 32 + * bytes of simulated data, and each time when the buffer is half-filled, the data is taken out of it and printed + * to the debug output. After completing all iterations, the application exits. + */ + +#include +#include + +#define TAG "ExampleEventLoopStreamBuffer" + +#define WORKER_ITERATION_COUNT (10) + +#define STREAM_BUFFER_SIZE (32) +#define STREAM_BUFFER_TRIG_LEVEL (STREAM_BUFFER_SIZE / 2) +#define STREAM_BUFFER_EVENT_AND_FLAGS (FuriEventLoopEventIn | FuriEventLoopEventFlagEdge) + +typedef struct { + FuriEventLoop* event_loop; + FuriThread* worker_thread; + FuriStreamBuffer* stream_buffer; +} EventLoopStreamBufferApp; + +// This funciton is being run in a separate thread to simulate data coming from a producer thread or some device. +static int32_t event_loop_stream_buffer_app_worker_thread(void* context) { + furi_assert(context); + EventLoopStreamBufferApp* app = context; + + FURI_LOG_I(TAG, "Worker thread started"); + + for(uint32_t i = 0; i < WORKER_ITERATION_COUNT; ++i) { + // Produce 32 bytes of simulated data. + for(uint32_t j = 0; j < STREAM_BUFFER_SIZE; ++j) { + // Simulate incoming data by generating a random byte. + uint8_t data = furi_hal_random_get() % 0xFF; + // Put the byte in the buffer. Depending on the use case, it may or may be not acceptable + // to wait for free space to become available. + furi_check( + furi_stream_buffer_send(app->stream_buffer, &data, 1, FuriWaitForever) == 1); + // Delay between 30 and 50 ms to slow down the output for clarity. + furi_delay_ms(30 + furi_hal_random_get() % 20); + } + } + + FURI_LOG_I(TAG, "All work done, worker thread out!"); + // Request the event loop to stop + furi_event_loop_stop(app->event_loop); + + return 0; +} + +// This function is being run each time when the number of bytes in the buffer is above its trigger level. +static bool + event_loop_stream_buffer_app_event_callback(FuriEventLoopObject* object, void* context) { + furi_assert(context); + EventLoopStreamBufferApp* app = context; + + furi_assert(object == app->stream_buffer); + + // Temporary buffer that can hold at most half of the stream buffer's capacity. + uint8_t data[STREAM_BUFFER_TRIG_LEVEL]; + // Receive the data. It is guaranteed that the amount of data in the buffer will be equal to + // or greater than the trigger level, therefore, no waiting delay is necessary. + furi_check( + furi_stream_buffer_receive(app->stream_buffer, data, sizeof(data), 0) == sizeof(data)); + + // Format the data for printing and print it to the debug output. + FuriString* tmp_str = furi_string_alloc(); + for(uint32_t i = 0; i < sizeof(data); ++i) { + furi_string_cat_printf(tmp_str, "%02X ", data[i]); + } + + FURI_LOG_I(TAG, "Received data: %s", furi_string_get_cstr(tmp_str)); + furi_string_free(tmp_str); + + return true; +} + +static EventLoopStreamBufferApp* event_loop_stream_buffer_app_alloc(void) { + EventLoopStreamBufferApp* app = malloc(sizeof(EventLoopStreamBufferApp)); + + // Create an event loop instance. + app->event_loop = furi_event_loop_alloc(); + // Create a worker thread instance. + app->worker_thread = furi_thread_alloc_ex( + "EventLoopStreamBufferWorker", 1024, event_loop_stream_buffer_app_worker_thread, app); + // Create a stream_buffer instance. + app->stream_buffer = furi_stream_buffer_alloc(STREAM_BUFFER_SIZE, STREAM_BUFFER_TRIG_LEVEL); + // Subscribe for the stream buffer IN events in edge triggered mode. + furi_event_loop_subscribe_stream_buffer( + app->event_loop, + app->stream_buffer, + STREAM_BUFFER_EVENT_AND_FLAGS, + event_loop_stream_buffer_app_event_callback, + app); + + return app; +} + +static void event_loop_stream_buffer_app_free(EventLoopStreamBufferApp* app) { + // IMPORTANT: The user code MUST unsubscribe from all events before deleting the event loop. + // Failure to do so will result in a crash. + furi_event_loop_unsubscribe(app->event_loop, app->stream_buffer); + // Delete all instances + furi_thread_free(app->worker_thread); + furi_stream_buffer_free(app->stream_buffer); + furi_event_loop_free(app->event_loop); + + free(app); +} + +static void event_loop_stream_buffer_app_run(EventLoopStreamBufferApp* app) { + furi_thread_start(app->worker_thread); + furi_event_loop_run(app->event_loop); + furi_thread_join(app->worker_thread); +} + +// The application's entry point - referenced in application.fam +int32_t example_event_loop_stream_buffer_app(void* arg) { + UNUSED(arg); + + EventLoopStreamBufferApp* app = event_loop_stream_buffer_app_alloc(); + event_loop_stream_buffer_app_run(app); + event_loop_stream_buffer_app_free(app); + + return 0; +} diff --git a/applications/examples/example_event_loop/example_event_loop_timer.c b/applications/examples/example_event_loop/example_event_loop_timer.c new file mode 100644 index 000000000..e255f6b61 --- /dev/null +++ b/applications/examples/example_event_loop/example_event_loop_timer.c @@ -0,0 +1,87 @@ +/** + * @file example_event_loop_timer.c + * @brief Example application that demonstrates FuriEventLoop's software timer capability. + * + * This application prints a countdown from 10 to 0 to the debug output and then exits. + * Despite only one timer being used in this example for clarity, an event loop instance can have + * an arbitrary number of independent timers of any type (periodic or one-shot). + * + */ +#include + +#define TAG "ExampleEventLoopTimer" + +#define COUNTDOWN_START_VALUE (10) +#define COUNTDOWN_INTERVAL_MS (1000) + +typedef struct { + FuriEventLoop* event_loop; + FuriEventLoopTimer* timer; + uint32_t countdown_value; +} EventLoopTimerApp; + +// This function is called each time the timer expires (i.e. once per 1000 ms (1s) in this example) +static void event_loop_timer_callback(void* context) { + furi_assert(context); + EventLoopTimerApp* app = context; + + // Print the countdown value + FURI_LOG_I(TAG, "T-00:00:%02lu", app->countdown_value); + + if(app->countdown_value == 0) { + // If the countdown reached 0, print the final line and stop the event loop + FURI_LOG_I(TAG, "Blast off to adventure!"); + // After this call, the control will be returned back to event_loop_timers_app_run() + furi_event_loop_stop(app->event_loop); + + } else { + // Decrement the countdown value + app->countdown_value -= 1; + } +} + +static EventLoopTimerApp* event_loop_timer_app_alloc(void) { + EventLoopTimerApp* app = malloc(sizeof(EventLoopTimerApp)); + + // Create an event loop instance. + app->event_loop = furi_event_loop_alloc(); + // Create a software timer instance. + // The timer is bound to the event loop instance and will execute in its context. + // Here, the timer type is periodic, i.e. it will restart automatically after expiring. + app->timer = furi_event_loop_timer_alloc( + app->event_loop, event_loop_timer_callback, FuriEventLoopTimerTypePeriodic, app); + // The countdown value will be tracked in this variable. + app->countdown_value = COUNTDOWN_START_VALUE; + + return app; +} + +static void event_loop_timer_app_free(EventLoopTimerApp* app) { + // IMPORTANT: All event loop timers MUST be deleted BEFORE deleting the event loop itself. + // Failure to do so will result in a crash. + furi_event_loop_timer_free(app->timer); + // With all timers deleted, it's safe to delete the event loop. + furi_event_loop_free(app->event_loop); + free(app); +} + +static void event_loop_timer_app_run(EventLoopTimerApp* app) { + FURI_LOG_I(TAG, "All systems go! Prepare for countdown!"); + + // Timers can be started either before the event loop is run, or in any + // callback function called by a running event loop. + furi_event_loop_timer_start(app->timer, COUNTDOWN_INTERVAL_MS); + // This call will block until furi_event_loop_stop() is called. + furi_event_loop_run(app->event_loop); +} + +// The application's entry point - referenced in application.fam +int32_t example_event_loop_timer_app(void* arg) { + UNUSED(arg); + + EventLoopTimerApp* app = event_loop_timer_app_alloc(); + event_loop_timer_app_run(app); + event_loop_timer_app_free(app); + + return 0; +} diff --git a/applications/examples/example_images/images/dolphin_71x25.png b/applications/examples/example_images/images/dolphin_71x25.png index 6b3f8aa59..26c21e235 100644 Binary files a/applications/examples/example_images/images/dolphin_71x25.png and b/applications/examples/example_images/images/dolphin_71x25.png differ diff --git a/applications/examples/example_number_input/ReadMe.md b/applications/examples/example_number_input/ReadMe.md new file mode 100644 index 000000000..9d5a0a9e5 --- /dev/null +++ b/applications/examples/example_number_input/ReadMe.md @@ -0,0 +1,7 @@ +# Number Input + +Simple keyboard that limits user inputs to a full number (integer). Useful to enforce correct entries without the need of intense validations after a user input. + +Definition of min/max values is required. Numbers are of type int32_t. If negative numbers are allowed withing min - max, an additional button is displayed to switch the sign between + and -. + +It is also possible to define a header text, shown in this example app with the 3 different input options. \ No newline at end of file diff --git a/applications/examples/example_number_input/application.fam b/applications/examples/example_number_input/application.fam new file mode 100644 index 000000000..58cff4496 --- /dev/null +++ b/applications/examples/example_number_input/application.fam @@ -0,0 +1,10 @@ +App( + appid="example_number_input", + name="Example: Number Input", + apptype=FlipperAppType.EXTERNAL, + entry_point="example_number_input", + requires=["gui"], + stack_size=1 * 1024, + fap_icon="example_number_input_10px.png", + fap_category="Examples", +) diff --git a/applications/examples/example_number_input/example_number_input.c b/applications/examples/example_number_input/example_number_input.c new file mode 100644 index 000000000..19d787ef5 --- /dev/null +++ b/applications/examples/example_number_input/example_number_input.c @@ -0,0 +1,79 @@ +#include "example_number_input.h" + +bool example_number_input_custom_event_callback(void* context, uint32_t event) { + furi_assert(context); + ExampleNumberInput* app = context; + return scene_manager_handle_custom_event(app->scene_manager, event); +} + +static bool example_number_input_back_event_callback(void* context) { + furi_assert(context); + ExampleNumberInput* app = context; + return scene_manager_handle_back_event(app->scene_manager); +} + +static ExampleNumberInput* example_number_input_alloc() { + ExampleNumberInput* app = malloc(sizeof(ExampleNumberInput)); + app->gui = furi_record_open(RECORD_GUI); + + app->view_dispatcher = view_dispatcher_alloc(); + + app->scene_manager = scene_manager_alloc(&example_number_input_scene_handlers, app); + view_dispatcher_set_event_callback_context(app->view_dispatcher, app); + view_dispatcher_set_custom_event_callback( + app->view_dispatcher, example_number_input_custom_event_callback); + view_dispatcher_set_navigation_event_callback( + app->view_dispatcher, example_number_input_back_event_callback); + + app->number_input = number_input_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, + ExampleNumberInputViewIdNumberInput, + number_input_get_view(app->number_input)); + + app->dialog_ex = dialog_ex_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, + ExampleNumberInputViewIdShowNumber, + dialog_ex_get_view(app->dialog_ex)); + + app->current_number = 5; + app->min_value = INT32_MIN; + app->max_value = INT32_MAX; + + return app; +} + +static void example_number_input_free(ExampleNumberInput* app) { + furi_assert(app); + + view_dispatcher_remove_view(app->view_dispatcher, ExampleNumberInputViewIdShowNumber); + dialog_ex_free(app->dialog_ex); + + view_dispatcher_remove_view(app->view_dispatcher, ExampleNumberInputViewIdNumberInput); + number_input_free(app->number_input); + + scene_manager_free(app->scene_manager); + view_dispatcher_free(app->view_dispatcher); + + furi_record_close(RECORD_GUI); + app->gui = NULL; + + //Remove whatever is left + free(app); +} + +int32_t example_number_input(void* p) { + UNUSED(p); + ExampleNumberInput* app = example_number_input_alloc(); + + view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + + scene_manager_next_scene(app->scene_manager, ExampleNumberInputSceneShowNumber); + + view_dispatcher_run(app->view_dispatcher); + + example_number_input_free(app); + + return 0; +} diff --git a/applications/examples/example_number_input/example_number_input.h b/applications/examples/example_number_input/example_number_input.h new file mode 100644 index 000000000..8d944e6fd --- /dev/null +++ b/applications/examples/example_number_input/example_number_input.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scenes/example_number_input_scene.h" + +typedef struct ExampleNumberInputShowNumber ExampleNumberInputShowNumber; + +typedef enum { + ExampleNumberInputViewIdShowNumber, + ExampleNumberInputViewIdNumberInput, +} ExampleNumberInputViewId; + +typedef struct { + Gui* gui; + SceneManager* scene_manager; + ViewDispatcher* view_dispatcher; + + NumberInput* number_input; + DialogEx* dialog_ex; + + int32_t current_number; + int32_t min_value; + int32_t max_value; +} ExampleNumberInput; diff --git a/applications/examples/example_number_input/example_number_input_10px.png b/applications/examples/example_number_input/example_number_input_10px.png new file mode 100644 index 000000000..bdb494fcd Binary files /dev/null and b/applications/examples/example_number_input/example_number_input_10px.png differ diff --git a/applications/examples/example_number_input/scenes/example_number_input_scene.c b/applications/examples/example_number_input/scenes/example_number_input_scene.c new file mode 100644 index 000000000..caf77fa8c --- /dev/null +++ b/applications/examples/example_number_input/scenes/example_number_input_scene.c @@ -0,0 +1,30 @@ +#include "example_number_input_scene.h" + +// Generate scene on_enter handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, +void (*const example_number_input_on_enter_handlers[])(void*) = { +#include "example_number_input_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_event handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, +bool (*const example_number_input_on_event_handlers[])(void* context, SceneManagerEvent event) = { +#include "example_number_input_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_exit handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, +void (*const example_number_input_on_exit_handlers[])(void* context) = { +#include "example_number_input_scene_config.h" +}; +#undef ADD_SCENE + +// Initialize scene handlers configuration structure +const SceneManagerHandlers example_number_input_scene_handlers = { + .on_enter_handlers = example_number_input_on_enter_handlers, + .on_event_handlers = example_number_input_on_event_handlers, + .on_exit_handlers = example_number_input_on_exit_handlers, + .scene_num = ExampleNumberInputSceneNum, +}; diff --git a/applications/system/storage_move_to_sd/scenes/storage_move_to_sd_scene.h b/applications/examples/example_number_input/scenes/example_number_input_scene.h similarity index 61% rename from applications/system/storage_move_to_sd/scenes/storage_move_to_sd_scene.h rename to applications/examples/example_number_input/scenes/example_number_input_scene.h index bdeb4a843..49fcd256f 100644 --- a/applications/system/storage_move_to_sd/scenes/storage_move_to_sd_scene.h +++ b/applications/examples/example_number_input/scenes/example_number_input_scene.h @@ -3,27 +3,27 @@ #include // Generate scene id and total number -#define ADD_SCENE(prefix, name, id) StorageMoveToSd##id, +#define ADD_SCENE(prefix, name, id) ExampleNumberInputScene##id, typedef enum { -#include "storage_move_to_sd_scene_config.h" - StorageMoveToSdSceneNum, -} StorageMoveToSdScene; +#include "example_number_input_scene_config.h" + ExampleNumberInputSceneNum, +} ExampleNumberInputScene; #undef ADD_SCENE -extern const SceneManagerHandlers storage_move_to_sd_scene_handlers; +extern const SceneManagerHandlers example_number_input_scene_handlers; // Generate scene on_enter handlers declaration #define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); -#include "storage_move_to_sd_scene_config.h" +#include "example_number_input_scene_config.h" #undef ADD_SCENE // Generate scene on_event handlers declaration #define ADD_SCENE(prefix, name, id) \ bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); -#include "storage_move_to_sd_scene_config.h" +#include "example_number_input_scene_config.h" #undef ADD_SCENE // Generate scene on_exit handlers declaration #define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); -#include "storage_move_to_sd_scene_config.h" +#include "example_number_input_scene_config.h" #undef ADD_SCENE diff --git a/applications/examples/example_number_input/scenes/example_number_input_scene_config.h b/applications/examples/example_number_input/scenes/example_number_input_scene_config.h new file mode 100644 index 000000000..71acbda52 --- /dev/null +++ b/applications/examples/example_number_input/scenes/example_number_input_scene_config.h @@ -0,0 +1,4 @@ +ADD_SCENE(example_number_input, input_number, InputNumber) +ADD_SCENE(example_number_input, show_number, ShowNumber) +ADD_SCENE(example_number_input, input_max, InputMax) +ADD_SCENE(example_number_input, input_min, InputMin) diff --git a/applications/examples/example_number_input/scenes/example_number_input_scene_input_max.c b/applications/examples/example_number_input/scenes/example_number_input_scene_input_max.c new file mode 100644 index 000000000..7478f58a7 --- /dev/null +++ b/applications/examples/example_number_input/scenes/example_number_input_scene_input_max.c @@ -0,0 +1,39 @@ +#include "../example_number_input.h" + +void example_number_input_scene_input_max_callback(void* context, int32_t number) { + ExampleNumberInput* app = context; + app->max_value = number; + view_dispatcher_send_custom_event(app->view_dispatcher, 0); +} + +void example_number_input_scene_input_max_on_enter(void* context) { + furi_assert(context); + ExampleNumberInput* app = context; + NumberInput* number_input = app->number_input; + + number_input_set_header_text(number_input, "Enter the maximum value"); + number_input_set_result_callback( + number_input, + example_number_input_scene_input_max_callback, + context, + app->max_value, + app->min_value, + INT32_MAX); + + view_dispatcher_switch_to_view(app->view_dispatcher, ExampleNumberInputViewIdNumberInput); +} + +bool example_number_input_scene_input_max_on_event(void* context, SceneManagerEvent event) { + ExampleNumberInput* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + scene_manager_previous_scene(app->scene_manager); + return true; + } + return consumed; +} + +void example_number_input_scene_input_max_on_exit(void* context) { + UNUSED(context); +} diff --git a/applications/examples/example_number_input/scenes/example_number_input_scene_input_min.c b/applications/examples/example_number_input/scenes/example_number_input_scene_input_min.c new file mode 100644 index 000000000..ad7656232 --- /dev/null +++ b/applications/examples/example_number_input/scenes/example_number_input_scene_input_min.c @@ -0,0 +1,39 @@ +#include "../example_number_input.h" + +void example_number_input_scene_input_min_callback(void* context, int32_t number) { + ExampleNumberInput* app = context; + app->min_value = number; + view_dispatcher_send_custom_event(app->view_dispatcher, 0); +} + +void example_number_input_scene_input_min_on_enter(void* context) { + furi_assert(context); + ExampleNumberInput* app = context; + NumberInput* number_input = app->number_input; + + number_input_set_header_text(number_input, "Enter the minimum value"); + number_input_set_result_callback( + number_input, + example_number_input_scene_input_min_callback, + context, + app->min_value, + INT32_MIN, + app->max_value); + + view_dispatcher_switch_to_view(app->view_dispatcher, ExampleNumberInputViewIdNumberInput); +} + +bool example_number_input_scene_input_min_on_event(void* context, SceneManagerEvent event) { + ExampleNumberInput* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + scene_manager_previous_scene(app->scene_manager); + return true; + } + return consumed; +} + +void example_number_input_scene_input_min_on_exit(void* context) { + UNUSED(context); +} diff --git a/applications/examples/example_number_input/scenes/example_number_input_scene_input_number.c b/applications/examples/example_number_input/scenes/example_number_input_scene_input_number.c new file mode 100644 index 000000000..d9b1fd52f --- /dev/null +++ b/applications/examples/example_number_input/scenes/example_number_input_scene_input_number.c @@ -0,0 +1,42 @@ +#include "../example_number_input.h" + +void example_number_input_scene_input_number_callback(void* context, int32_t number) { + ExampleNumberInput* app = context; + app->current_number = number; + view_dispatcher_send_custom_event(app->view_dispatcher, 0); +} + +void example_number_input_scene_input_number_on_enter(void* context) { + furi_assert(context); + ExampleNumberInput* app = context; + NumberInput* number_input = app->number_input; + + char str[50]; + snprintf(str, sizeof(str), "Set Number (%ld - %ld)", app->min_value, app->max_value); + + number_input_set_header_text(number_input, str); + number_input_set_result_callback( + number_input, + example_number_input_scene_input_number_callback, + context, + app->current_number, + app->min_value, + app->max_value); + + view_dispatcher_switch_to_view(app->view_dispatcher, ExampleNumberInputViewIdNumberInput); +} + +bool example_number_input_scene_input_number_on_event(void* context, SceneManagerEvent event) { + ExampleNumberInput* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { //Back button pressed + scene_manager_previous_scene(app->scene_manager); + return true; + } + return consumed; +} + +void example_number_input_scene_input_number_on_exit(void* context) { + UNUSED(context); +} diff --git a/applications/examples/example_number_input/scenes/example_number_input_scene_show_number.c b/applications/examples/example_number_input/scenes/example_number_input_scene_show_number.c new file mode 100644 index 000000000..2afdaf5c1 --- /dev/null +++ b/applications/examples/example_number_input/scenes/example_number_input_scene_show_number.c @@ -0,0 +1,66 @@ +#include "../example_number_input.h" + +static void + example_number_input_scene_confirm_dialog_callback(DialogExResult result, void* context) { + ExampleNumberInput* app = context; + + view_dispatcher_send_custom_event(app->view_dispatcher, result); +} + +static void example_number_input_scene_update_view(void* context) { + ExampleNumberInput* app = context; + DialogEx* dialog_ex = app->dialog_ex; + + dialog_ex_set_header(dialog_ex, "The number is", 64, 0, AlignCenter, AlignTop); + + static char buffer[12]; //needs static for extended lifetime + + snprintf(buffer, sizeof(buffer), "%ld", app->current_number); + dialog_ex_set_text(dialog_ex, buffer, 64, 29, AlignCenter, AlignCenter); + + dialog_ex_set_left_button_text(dialog_ex, "Min"); + dialog_ex_set_right_button_text(dialog_ex, "Max"); + dialog_ex_set_center_button_text(dialog_ex, "Change"); + + dialog_ex_set_result_callback(dialog_ex, example_number_input_scene_confirm_dialog_callback); + dialog_ex_set_context(dialog_ex, app); +} + +void example_number_input_scene_show_number_on_enter(void* context) { + furi_assert(context); + ExampleNumberInput* app = context; + + example_number_input_scene_update_view(app); + + view_dispatcher_switch_to_view(app->view_dispatcher, ExampleNumberInputViewIdShowNumber); +} + +bool example_number_input_scene_show_number_on_event(void* context, SceneManagerEvent event) { + ExampleNumberInput* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + switch(event.event) { + case DialogExResultCenter: + scene_manager_next_scene(app->scene_manager, ExampleNumberInputSceneInputNumber); + consumed = true; + break; + case DialogExResultLeft: + scene_manager_next_scene(app->scene_manager, ExampleNumberInputSceneInputMin); + consumed = true; + break; + case DialogExResultRight: + scene_manager_next_scene(app->scene_manager, ExampleNumberInputSceneInputMax); + consumed = true; + break; + default: + break; + } + } + + return consumed; +} + +void example_number_input_scene_show_number_on_exit(void* context) { + UNUSED(context); +} diff --git a/applications/examples/example_thermo/example_thermo_10px.png b/applications/examples/example_thermo/example_thermo_10px.png index 3d527f306..bc42d190c 100644 Binary files a/applications/examples/example_thermo/example_thermo_10px.png and b/applications/examples/example_thermo/example_thermo_10px.png differ diff --git a/applications/examples/example_view_dispatcher/application.fam b/applications/examples/example_view_dispatcher/application.fam new file mode 100644 index 000000000..f7b743bcf --- /dev/null +++ b/applications/examples/example_view_dispatcher/application.fam @@ -0,0 +1,8 @@ +App( + appid="example_view_dispatcher", + name="Example: ViewDispatcher", + apptype=FlipperAppType.EXTERNAL, + entry_point="example_view_dispatcher_app", + requires=["gui"], + fap_category="Examples", +) diff --git a/applications/examples/example_view_dispatcher/example_view_dispatcher.c b/applications/examples/example_view_dispatcher/example_view_dispatcher.c new file mode 100644 index 000000000..71d29edfd --- /dev/null +++ b/applications/examples/example_view_dispatcher/example_view_dispatcher.c @@ -0,0 +1,173 @@ +/** + * @file example_view_dispatcher.c + * @brief Example application demonstrating the usage of the ViewDispatcher library. + * + * This application can display one of two views: either a Widget or a Submenu. + * Each view has its own way of switching to another one: + * + * - A center button in the Widget view. + * - A submenu item in the Submenu view + * + * Press either to switch to a different view. Press Back to exit the application. + * + */ + +#include +#include + +#include +#include + +// Enumeration of the view indexes. +typedef enum { + ViewIndexWidget, + ViewIndexSubmenu, + ViewIndexCount, +} ViewIndex; + +// Enumeration of submenu items. +typedef enum { + SubmenuIndexNothing, + SubmenuIndexSwitchView, +} SubmenuIndex; + +// Main application structure. +typedef struct { + ViewDispatcher* view_dispatcher; + Widget* widget; + Submenu* submenu; +} ExampleViewDispatcherApp; + +// This function is called when the user has pressed the Back key. +static bool example_view_dispatcher_app_navigation_callback(void* context) { + furi_assert(context); + ExampleViewDispatcherApp* app = context; + // Back means exit the application, which can be done by stopping the ViewDispatcher. + view_dispatcher_stop(app->view_dispatcher); + return true; +} + +// This function is called when there are custom events to process. +static bool example_view_dispatcher_app_custom_event_callback(void* context, uint32_t event) { + furi_assert(context); + ExampleViewDispatcherApp* app = context; + // The event numerical value can mean different things (the application is responsible to uphold its chosen convention) + // In this example, the only possible meaning is the view index to switch to. + furi_assert(event < ViewIndexCount); + // Switch to the requested view. + view_dispatcher_switch_to_view(app->view_dispatcher, event); + + return true; +} + +// This function is called when the user presses the "Switch View" button on the Widget view. +static void example_view_dispatcher_app_button_callback( + GuiButtonType button_type, + InputType input_type, + void* context) { + furi_assert(context); + ExampleViewDispatcherApp* app = context; + // Only request the view switch if the user short-presses the Center button. + if(button_type == GuiButtonTypeCenter && input_type == InputTypeShort) { + // Request switch to the Submenu view via the custom event queue. + view_dispatcher_send_custom_event(app->view_dispatcher, ViewIndexSubmenu); + } +} + +// This function is called when the user activates the "Switch View" submenu item. +static void example_view_dispatcher_app_submenu_callback(void* context, uint32_t index) { + furi_assert(context); + ExampleViewDispatcherApp* app = context; + // Only request the view switch if the user activates the "Switch View" item. + if(index == SubmenuIndexSwitchView) { + // Request switch to the Widget view via the custom event queue. + view_dispatcher_send_custom_event(app->view_dispatcher, ViewIndexWidget); + } +} + +// Application constructor function. +static ExampleViewDispatcherApp* example_view_dispatcher_app_alloc() { + ExampleViewDispatcherApp* app = malloc(sizeof(ExampleViewDispatcherApp)); + // Access the GUI API instance. + Gui* gui = furi_record_open(RECORD_GUI); + // Create and initialize the Widget view. + app->widget = widget_alloc(); + widget_add_string_multiline_element( + app->widget, 64, 32, AlignCenter, AlignCenter, FontSecondary, "Press the Button below"); + widget_add_button_element( + app->widget, + GuiButtonTypeCenter, + "Switch View", + example_view_dispatcher_app_button_callback, + app); + // Create and initialize the Submenu view. + app->submenu = submenu_alloc(); + submenu_add_item(app->submenu, "Do Nothing", SubmenuIndexNothing, NULL, NULL); + submenu_add_item( + app->submenu, + "Switch View", + SubmenuIndexSwitchView, + example_view_dispatcher_app_submenu_callback, + app); + // Create the ViewDispatcher instance. + app->view_dispatcher = view_dispatcher_alloc(); + // Let the GUI know about this ViewDispatcher instance. + view_dispatcher_attach_to_gui(app->view_dispatcher, gui, ViewDispatcherTypeFullscreen); + // Register the views within the ViewDispatcher instance. This alone will not show any of them on the screen. + // Each view must have its own index to refer to it later (it is best done via an enumeration as shown here). + view_dispatcher_add_view(app->view_dispatcher, ViewIndexWidget, widget_get_view(app->widget)); + view_dispatcher_add_view( + app->view_dispatcher, ViewIndexSubmenu, submenu_get_view(app->submenu)); + // Set the custom event callback. It will be called each time a custom event is scheduled + // using the view_dispatcher_send_custom_callback() function. + view_dispatcher_set_custom_event_callback( + app->view_dispatcher, example_view_dispatcher_app_custom_event_callback); + // Set the navigation, or back button callback. It will be called if the user pressed the Back button + // and the event was not handled in the currently displayed view. + view_dispatcher_set_navigation_event_callback( + app->view_dispatcher, example_view_dispatcher_app_navigation_callback); + // The context will be passed to the callbacks as a parameter, so we have access to our application object. + view_dispatcher_set_event_callback_context(app->view_dispatcher, app); + + return app; +} + +// Application destructor function. +static void example_view_dispatcher_app_free(ExampleViewDispatcherApp* app) { + // All views must be un-registered (removed) from a ViewDispatcher instance + // before deleting it. Failure to do so will result in a crash. + view_dispatcher_remove_view(app->view_dispatcher, ViewIndexWidget); + view_dispatcher_remove_view(app->view_dispatcher, ViewIndexSubmenu); + // Now it is safe to delete the ViewDispatcher instance. + view_dispatcher_free(app->view_dispatcher); + // Delete the views + widget_free(app->widget); + submenu_free(app->submenu); + // End access to hte the GUI API. + furi_record_close(RECORD_GUI); + // Free the remaining memory. + free(app); +} + +static void example_view_dispatcher_app_run(ExampleViewDispatcherApp* app) { + // Display the Widget view on the screen. + view_dispatcher_switch_to_view(app->view_dispatcher, ViewIndexWidget); + // This function will block until view_dispatcher_stop() is called. + // Internally, it uses a FuriEventLoop (see FuriEventLoop examples for more info on this). + view_dispatcher_run(app->view_dispatcher); +} + +/******************************************************************* + * vvv START HERE vvv + * + * The application's entry point - referenced in application.fam + *******************************************************************/ +int32_t example_view_dispatcher_app(void* arg) { + UNUSED(arg); + + ExampleViewDispatcherApp* app = example_view_dispatcher_app_alloc(); + example_view_dispatcher_app_run(app); + example_view_dispatcher_app_free(app); + + return 0; +} diff --git a/applications/examples/example_view_holder/application.fam b/applications/examples/example_view_holder/application.fam new file mode 100644 index 000000000..19ad8d2ac --- /dev/null +++ b/applications/examples/example_view_holder/application.fam @@ -0,0 +1,8 @@ +App( + appid="example_view_holder", + name="Example: ViewHolder", + apptype=FlipperAppType.EXTERNAL, + entry_point="example_view_holder_app", + requires=["gui"], + fap_category="Examples", +) diff --git a/applications/examples/example_view_holder/example_view_holder.c b/applications/examples/example_view_holder/example_view_holder.c new file mode 100644 index 000000000..24907dbc2 --- /dev/null +++ b/applications/examples/example_view_holder/example_view_holder.c @@ -0,0 +1,78 @@ +/** + * @file example_view_holder.c + * @brief Example application demonstrating the usage of the ViewHolder library. + * + * This application will display a text box with some scrollable text in it. + * Press the Back key to exit the application. + */ + +#include +#include +#include + +#include + +// This function will be called when the user presses the Back button. +static void example_view_holder_back_callback(void* context) { + FuriApiLock exit_lock = context; + // Unlock the exit lock, thus enabling the app to exit. + api_lock_unlock(exit_lock); +} + +int32_t example_view_holder_app(void* arg) { + UNUSED(arg); + + // Access the GUI API instance. + Gui* gui = furi_record_open(RECORD_GUI); + // Create a TextBox view. The Gui object only accepts + // ViewPort instances, so we will need to address that later. + TextBox* text_box = text_box_alloc(); + // Set some text so that the text box is not empty. + text_box_set_text( + text_box, + "ViewHolder is being used\n" + "to show this TextBox view.\n\n" + "Scroll down to see more.\n\n\n" + "Press \"Back\" to exit."); + + // Create a ViewHolder instance. It will serve as an adapter to convert + // between the View type provided by the TextBox view and the ViewPort type + // that the GUI can actually display. + ViewHolder* view_holder = view_holder_alloc(); + // Let the GUI know about this ViewHolder instance. + view_holder_attach_to_gui(view_holder, gui); + // Set the view that we want to display. + view_holder_set_view(view_holder, text_box_get_view(text_box)); + + // The part below is not really related to this example, but is necessary for it to function. + // We need to somehow stall the application thread so that the view stays on the screen (otherwise + // the app will just exit and won't display anything) and at the same time we need a way to quit out + // of the application. + + // In this example, a simple FuriApiLock instance is used. A real-world application is likely to have some + // kind of event handling loop here instead. (see the ViewDispatcher example or one of FuriEventLoop + // examples for that). + + // Create a pre-locked FuriApiLock instance. + FuriApiLock exit_lock = api_lock_alloc_locked(); + // Set a Back event callback for the ViewHolder instance. It will be called when the user + // presses the Back button. We pass the exit lock instance as the context to be able to access + // it inside the callback function. + view_holder_set_back_callback(view_holder, example_view_holder_back_callback, exit_lock); + + // This call will block the application thread from running until the exit lock gets unlocked somehow + // (the only way it can happen in this example is via the back callback). + api_lock_wait_unlock_and_free(exit_lock); + + // The back key has been pressed, which unlocked the exit lock. The application is about to exit. + + // The view must be removed from a ViewHolder instance before deleting it. + view_holder_set_view(view_holder, NULL); + // Delete everything to prevent memory leaks. + view_holder_free(view_holder); + text_box_free(text_box); + // End access to the GUI API. + furi_record_close(RECORD_GUI); + + return 0; +} diff --git a/applications/external b/applications/external index fa9648df8..70fae8dc9 160000 --- a/applications/external +++ b/applications/external @@ -1 +1 @@ -Subproject commit fa9648df8ee55cb0a0b08fcb9458c133d46e4670 +Subproject commit 70fae8dc939730232600f134b7feeed468c16882 diff --git a/applications/main/archive/archive.c b/applications/main/archive/archive.c index 432417c6e..7746e2dfe 100644 --- a/applications/main/archive/archive.c +++ b/applications/main/archive/archive.c @@ -30,7 +30,6 @@ static ArchiveApp* archive_alloc(void) { archive->view_dispatcher = view_dispatcher_alloc(); ViewDispatcher* view_dispatcher = archive->view_dispatcher; - view_dispatcher_enable_queue(view_dispatcher); view_dispatcher_set_event_callback_context(view_dispatcher, archive); view_dispatcher_set_custom_event_callback(view_dispatcher, archive_custom_event_callback); view_dispatcher_set_navigation_event_callback(view_dispatcher, archive_back_event_callback); diff --git a/applications/main/archive/helpers/archive_browser.c b/applications/main/archive/helpers/archive_browser.c index b992e1bec..ea93c9e05 100644 --- a/applications/main/archive/helpers/archive_browser.c +++ b/applications/main/archive/helpers/archive_browser.c @@ -510,18 +510,15 @@ void archive_favorites_move_mode(ArchiveBrowserView* browser, bool active) { } static bool archive_is_dir_exists(FuriString* path) { - if(furi_string_equal(path, STORAGE_INT_PATH_PREFIX) || - furi_string_equal(path, STORAGE_EXT_PATH_PREFIX) || - furi_string_equal(path, STORAGE_MNT_PATH_PREFIX)) { - return true; - } bool state = false; FileInfo file_info; Storage* storage = furi_record_open(RECORD_STORAGE); - if(storage_common_stat(storage, furi_string_get_cstr(path), &file_info) == FSE_OK) { - if(file_info_is_dir(&file_info)) { - state = true; - } + + if(furi_string_equal(path, STORAGE_EXT_PATH_PREFIX) || + furi_string_equal(path, STORAGE_MNT_PATH_PREFIX)) { + state = storage_sd_status(storage) == FSE_OK; + } else if(storage_common_stat(storage, furi_string_get_cstr(path), &file_info) == FSE_OK) { + state = file_info_is_dir(&file_info); } furi_record_close(RECORD_STORAGE); return state; diff --git a/applications/main/archive/helpers/archive_favorites.h b/applications/main/archive/helpers/archive_favorites.h index 219f87045..be9bf2866 100644 --- a/applications/main/archive/helpers/archive_favorites.h +++ b/applications/main/archive/helpers/archive_favorites.h @@ -2,8 +2,8 @@ #include -#define ARCHIVE_FAV_PATH ANY_PATH("favorites.txt") -#define ARCHIVE_FAV_TEMP_PATH ANY_PATH("favorites.tmp") +#define ARCHIVE_FAV_PATH EXT_PATH("favorites.txt") +#define ARCHIVE_FAV_TEMP_PATH EXT_PATH("favorites.tmp") uint16_t archive_favorites_count(void); bool archive_favorites_read(void* context); diff --git a/applications/main/archive/helpers/archive_files.c b/applications/main/archive/helpers/archive_files.c index 8d1d5dc1a..7c61e1b24 100644 --- a/applications/main/archive/helpers/archive_files.c +++ b/applications/main/archive/helpers/archive_files.c @@ -18,7 +18,7 @@ void archive_set_file_type(ArchiveFile_t* file, const char* path, bool is_folder } else { for(size_t i = 0; i < COUNT_OF(known_ext); i++) { if((known_ext[i][0] == '?') || (known_ext[i][0] == '*')) continue; - if(furi_string_end_with(file->path, known_ext[i])) { + if(furi_string_end_withi(file->path, known_ext[i])) { // Check for .txt containing folder if(strcmp(known_ext[i], ".txt") == 0) { const char* txt_path = NULL; diff --git a/applications/main/bad_kb/bad_kb_app.c b/applications/main/bad_kb/bad_kb_app.c index 21e160264..db63af77e 100644 --- a/applications/main/bad_kb/bad_kb_app.c +++ b/applications/main/bad_kb/bad_kb_app.c @@ -320,7 +320,6 @@ BadKbApp* bad_kb_app_alloc(char* arg) { app->dialogs = furi_record_open(RECORD_DIALOGS); app->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_enable_queue(app->view_dispatcher); app->scene_manager = scene_manager_alloc(&bad_kb_scene_handlers, app); diff --git a/applications/main/bad_kb/helpers/ble_hid.c b/applications/main/bad_kb/helpers/ble_hid.c index 2240bca35..2f6dd8c2a 100644 --- a/applications/main/bad_kb/helpers/ble_hid.c +++ b/applications/main/bad_kb/helpers/ble_hid.c @@ -373,6 +373,12 @@ bool ble_profile_hid_mouse_scroll(FuriHalBleProfileBase* profile, int8_t delta) return state; } +// AN5289: 4.7, in order to use flash controller interval must be at least 25ms + advertisement, which is 30 ms +// Since we don't use flash controller anymore interval can be lowered to 7.5ms +#define CONNECTION_INTERVAL_MIN (0x0006) +// Up to 45 ms +#define CONNECTION_INTERVAL_MAX (0x24) + static GapConfig template_config = { .adv_service_uuid = HUMAN_INTERFACE_DEVICE_SERVICE_UUID, .appearance_char = GAP_APPEARANCE_KEYBOARD, @@ -380,8 +386,8 @@ static GapConfig template_config = { .pairing_method = GapPairingPinCodeVerifyYesNo, .conn_param = { - .conn_int_min = 0x18, // 30 ms - .conn_int_max = 0x24, // 45 ms + .conn_int_min = CONNECTION_INTERVAL_MIN, + .conn_int_max = CONNECTION_INTERVAL_MAX, .slave_latency = 0, .supervisor_timeout = 0, }, diff --git a/applications/main/bad_kb/icon.png b/applications/main/bad_kb/icon.png index 037474aa3..2b5a3bf97 100644 Binary files a/applications/main/bad_kb/icon.png and b/applications/main/bad_kb/icon.png differ diff --git a/applications/main/gpio/gpio_app.c b/applications/main/gpio/gpio_app.c index 1d201a730..178f30c66 100644 --- a/applications/main/gpio/gpio_app.c +++ b/applications/main/gpio/gpio_app.c @@ -32,7 +32,6 @@ GpioApp* gpio_app_alloc(void) { app->view_dispatcher = view_dispatcher_alloc(); app->scene_manager = scene_manager_alloc(&gpio_scene_handlers, app); - view_dispatcher_enable_queue(app->view_dispatcher); view_dispatcher_set_event_callback_context(app->view_dispatcher, app); view_dispatcher_set_custom_event_callback( diff --git a/applications/main/gpio/icon.png b/applications/main/gpio/icon.png index 4a6eccf05..7b54bb5cb 100644 Binary files a/applications/main/gpio/icon.png and b/applications/main/gpio/icon.png differ diff --git a/applications/main/ibutton/ibutton.c b/applications/main/ibutton/ibutton.c index 26e599b48..6619041c5 100644 --- a/applications/main/ibutton/ibutton.c +++ b/applications/main/ibutton/ibutton.c @@ -87,7 +87,6 @@ iButton* ibutton_alloc(void) { ibutton->scene_manager = scene_manager_alloc(&ibutton_scene_handlers, ibutton); ibutton->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_enable_queue(ibutton->view_dispatcher); view_dispatcher_set_event_callback_context(ibutton->view_dispatcher, ibutton); view_dispatcher_set_custom_event_callback( ibutton->view_dispatcher, ibutton_custom_event_callback); diff --git a/applications/main/ibutton/ibutton_i.h b/applications/main/ibutton/ibutton_i.h index ece61e236..aef4fb41c 100644 --- a/applications/main/ibutton/ibutton_i.h +++ b/applications/main/ibutton/ibutton_i.h @@ -28,7 +28,7 @@ #include "ibutton_custom_event.h" #include "scenes/ibutton_scene.h" -#define IBUTTON_APP_FOLDER ANY_PATH("ibutton") +#define IBUTTON_APP_FOLDER EXT_PATH("ibutton") #define IBUTTON_APP_FILENAME_PREFIX "iBtn" #define IBUTTON_APP_FILENAME_EXTENSION ".ibtn" diff --git a/applications/main/ibutton/icon.png b/applications/main/ibutton/icon.png index 2fdaf123a..f73af065f 100644 Binary files a/applications/main/ibutton/icon.png and b/applications/main/ibutton/icon.png differ diff --git a/applications/main/infrared/icon.png b/applications/main/infrared/icon.png index 22c986180..36c214f3b 100644 Binary files a/applications/main/infrared/icon.png and b/applications/main/infrared/icon.png differ diff --git a/applications/main/infrared/infrared_app.c b/applications/main/infrared/infrared_app.c index a9bcbb95c..70a691f55 100644 --- a/applications/main/infrared/infrared_app.c +++ b/applications/main/infrared/infrared_app.c @@ -150,7 +150,6 @@ static InfraredApp* infrared_alloc(void) { infrared->gui = furi_record_open(RECORD_GUI); ViewDispatcher* view_dispatcher = infrared->view_dispatcher; - view_dispatcher_enable_queue(view_dispatcher); view_dispatcher_set_event_callback_context(view_dispatcher, infrared); view_dispatcher_set_custom_event_callback(view_dispatcher, infrared_custom_event_callback); view_dispatcher_set_navigation_event_callback(view_dispatcher, infrared_back_event_callback); @@ -476,6 +475,7 @@ static void infrared_load_settings(InfraredApp* infrared) { INFRARED_SETTINGS_MAGIC, INFRARED_SETTINGS_VERSION)) { FURI_LOG_D(TAG, "Failed to load settings, using defaults"); + // infrared_save_settings(infrared); } infrared_set_tx_pin(infrared, settings.tx_pin); diff --git a/applications/main/infrared/infrared_app.h b/applications/main/infrared/infrared_app.h index 545fada9f..fedfd8af9 100644 --- a/applications/main/infrared/infrared_app.h +++ b/applications/main/infrared/infrared_app.h @@ -17,7 +17,7 @@ typedef struct InfraredApp InfraredApp; #include #include -#define INFRARED_SETTINGS_PATH EXT_PATH("infrared/.infrared.settings") +#define INFRARED_SETTINGS_PATH INT_PATH(".infrared.settings") #define INFRARED_SETTINGS_VERSION (1) #define INFRARED_SETTINGS_MAGIC (0x1F) diff --git a/applications/main/infrared/infrared_app_i.h b/applications/main/infrared/infrared_app_i.h index d353b2503..75d4e230d 100644 --- a/applications/main/infrared/infrared_app_i.h +++ b/applications/main/infrared/infrared_app_i.h @@ -46,7 +46,7 @@ #define INFRARED_MAX_BUTTON_NAME_LENGTH 22 #define INFRARED_MAX_REMOTE_NAME_LENGTH 22 -#define INFRARED_APP_FOLDER ANY_PATH("infrared") +#define INFRARED_APP_FOLDER EXT_PATH("infrared") #define INFRARED_APP_EXTENSION ".ir" #define INFRARED_DEFAULT_REMOTE_NAME "Remote" diff --git a/applications/main/lfrfid/icon.png b/applications/main/lfrfid/icon.png index ce01284a2..fd3947ff3 100644 Binary files a/applications/main/lfrfid/icon.png and b/applications/main/lfrfid/icon.png differ diff --git a/applications/main/lfrfid/lfrfid.c b/applications/main/lfrfid/lfrfid.c index 2b1ca02c1..b93e07222 100644 --- a/applications/main/lfrfid/lfrfid.c +++ b/applications/main/lfrfid/lfrfid.c @@ -78,7 +78,6 @@ static LfRfid* lfrfid_alloc(void) { lfrfid->view_dispatcher = view_dispatcher_alloc(); lfrfid->scene_manager = scene_manager_alloc(&lfrfid_scene_handlers, lfrfid); - view_dispatcher_enable_queue(lfrfid->view_dispatcher); view_dispatcher_set_event_callback_context(lfrfid->view_dispatcher, lfrfid); view_dispatcher_set_custom_event_callback( lfrfid->view_dispatcher, lfrfid_debug_custom_event_callback); diff --git a/applications/main/lfrfid/lfrfid_i.h b/applications/main/lfrfid/lfrfid_i.h index e8f2593a8..f2cbc3132 100644 --- a/applications/main/lfrfid/lfrfid_i.h +++ b/applications/main/lfrfid/lfrfid_i.h @@ -37,7 +37,7 @@ #define LFRFID_TEXT_STORE_SIZE 40 -#define LFRFID_APP_FOLDER ANY_PATH("lfrfid") +#define LFRFID_APP_FOLDER EXT_PATH("lfrfid") #define LFRFID_SD_FOLDER EXT_PATH("lfrfid") #define LFRFID_APP_FILENAME_PREFIX "RFID" #define LFRFID_APP_FILENAME_EXTENSION ".rfid" diff --git a/applications/main/momentum_app/icon.png b/applications/main/momentum_app/icon.png index 606a6d13c..ae8240110 100644 Binary files a/applications/main/momentum_app/icon.png and b/applications/main/momentum_app/icon.png differ diff --git a/applications/main/momentum_app/mock_imports/mock_desktop.c b/applications/main/momentum_app/mock_imports/mock_desktop.c new file mode 100644 index 000000000..e46770596 --- /dev/null +++ b/applications/main/momentum_app/mock_imports/mock_desktop.c @@ -0,0 +1,7 @@ +// Since settings app is external, it cannot access firmware functions +// For simple utils like this, easier to include C code in app rather than exposing to API +// Instead of copying the file, can (ab)use the preprocessor to insert the source code here +// Then, we still use the Header from original code as if nothing happened + +// desktop_api_get_settings(), desktop_api_set_settings() +#include diff --git a/applications/main/momentum_app/mock_imports/mock_dolphin_state.c b/applications/main/momentum_app/mock_imports/mock_dolphin_state.c new file mode 100644 index 000000000..2c8356efe --- /dev/null +++ b/applications/main/momentum_app/mock_imports/mock_dolphin_state.c @@ -0,0 +1,7 @@ +// Since settings app is external, it cannot access firmware functions +// For simple utils like this, easier to include C code in app rather than exposing to API +// Instead of copying the file, can (ab)use the preprocessor to insert the source code here +// Then, we still use the Header from original code as if nothing happened + +// DOLPHIN_LEVELS, DOLPHIN_LEVEL_COUNT +#include diff --git a/applications/main/momentum_app/momentum_app.c b/applications/main/momentum_app/momentum_app.c index 58ae5034c..326e608d1 100644 --- a/applications/main/momentum_app/momentum_app.c +++ b/applications/main/momentum_app/momentum_app.c @@ -8,7 +8,8 @@ static bool momentum_app_custom_event_callback(void* context, uint32_t event) { void callback_reboot(void* context) { UNUSED(context); - power_reboot(PowerBootModeNormal); + Power* power = furi_record_open(RECORD_POWER); + power_reboot(power, PowerBootModeNormal); } bool momentum_app_apply(MomentumApp* app) { @@ -26,6 +27,10 @@ bool momentum_app_apply(MomentumApp* app) { stream_free(stream); } + if(app->save_desktop) { + desktop_api_set_settings(app->desktop, &app->desktop_settings); + } + if(app->save_subghz_freqs) { FlipperFormat* file = flipper_format_file_alloc(storage); do { @@ -97,7 +102,7 @@ bool momentum_app_apply(MomentumApp* app) { } } - if(app->save_level || app->save_angry) { + if(app->save_dolphin) { Dolphin* dolphin = furi_record_open(RECORD_DOLPHIN); if(app->save_level) { int32_t xp = app->dolphin_level > 1 ? DOLPHIN_LEVELS[app->dolphin_level - 2] : 0; @@ -107,7 +112,8 @@ bool momentum_app_apply(MomentumApp* app) { dolphin->state->data.butthurt = app->dolphin_angry; } dolphin->state->dirty = true; - dolphin_state_save(dolphin->state); + dolphin_flush(dolphin); + dolphin_reload_state(dolphin); furi_record_close(RECORD_DOLPHIN); } @@ -180,6 +186,7 @@ static void momentum_app_push_mainmenu_app(MomentumApp* app, FuriString* label, MomentumApp* momentum_app_alloc() { MomentumApp* app = malloc(sizeof(MomentumApp)); app->gui = furi_record_open(RECORD_GUI); + app->desktop = furi_record_open(RECORD_DESKTOP); app->dialogs = furi_record_open(RECORD_DIALOGS); app->expansion = furi_record_open(RECORD_EXPANSION); app->notification = furi_record_open(RECORD_NOTIFICATION); @@ -187,7 +194,7 @@ MomentumApp* momentum_app_alloc() { // View Dispatcher and Scene Manager app->view_dispatcher = view_dispatcher_alloc(); app->scene_manager = scene_manager_alloc(&momentum_app_scene_handlers, app); - view_dispatcher_enable_queue(app->view_dispatcher); + view_dispatcher_set_event_callback_context(app->view_dispatcher, app); view_dispatcher_set_custom_event_callback( @@ -216,6 +223,12 @@ MomentumApp* momentum_app_alloc() { view_dispatcher_add_view( app->view_dispatcher, MomentumAppViewByteInput, byte_input_get_view(app->byte_input)); + app->number_input = number_input_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, + MomentumAppViewNumberInput, + number_input_get_view(app->number_input)); + app->popup = popup_alloc(); view_dispatcher_add_view( app->view_dispatcher, MomentumAppViewPopup, popup_get_view(app->popup)); @@ -275,6 +288,8 @@ MomentumApp* momentum_app_alloc() { furi_string_set(line, "125 kHz RFID"); } else if(furi_string_equal(line, "SubGHz")) { furi_string_set(line, "Sub-GHz"); + } else if(furi_string_equal(line, "Xtreme")) { + furi_string_set(line, "Momentum"); } } if(furi_string_start_with(line, "/")) { @@ -322,6 +337,8 @@ MomentumApp* momentum_app_alloc() { file_stream_close(stream); stream_free(stream); + desktop_api_get_settings(app->desktop, &app->desktop_settings); + FlipperFormat* file = flipper_format_file_alloc(storage); FrequencyList_init(app->subghz_static_freqs); FrequencyList_init(app->subghz_hopper_freqs); @@ -410,6 +427,8 @@ void momentum_app_free(MomentumApp* app) { text_input_free(app->text_input); view_dispatcher_remove_view(app->view_dispatcher, MomentumAppViewByteInput); byte_input_free(app->byte_input); + view_dispatcher_remove_view(app->view_dispatcher, MomentumAppViewNumberInput); + number_input_free(app->number_input); view_dispatcher_remove_view(app->view_dispatcher, MomentumAppViewPopup); popup_free(app->popup); view_dispatcher_remove_view(app->view_dispatcher, MomentumAppViewDialogEx); @@ -445,6 +464,7 @@ void momentum_app_free(MomentumApp* app) { furi_record_close(RECORD_NOTIFICATION); furi_record_close(RECORD_EXPANSION); furi_record_close(RECORD_DIALOGS); + furi_record_close(RECORD_DESKTOP); furi_record_close(RECORD_GUI); free(app); } diff --git a/applications/main/momentum_app/momentum_app.h b/applications/main/momentum_app/momentum_app.h index 85e4dd318..00f9f5e1b 100644 --- a/applications/main/momentum_app/momentum_app.h +++ b/applications/main/momentum_app/momentum_app.h @@ -1,51 +1,60 @@ #pragma once +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include #include -#include -#include -#include -#include -#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include -#include #include -#include #include -#include -#include -#include -#include -#include -#include -#include #include +#include "scenes/momentum_app_scene.h" + ARRAY_DEF(CharList, char*) typedef struct { Gui* gui; + Desktop* desktop; DialogsApp* dialogs; Expansion* expansion; NotificationApp* notification; SceneManager* scene_manager; ViewDispatcher* view_dispatcher; + VariableItemList* var_item_list; Submenu* submenu; TextInput* text_input; ByteInput* byte_input; + NumberInput* number_input; Popup* popup; DialogEx* dialog_ex; @@ -54,12 +63,12 @@ typedef struct { CharList_t mainmenu_app_labels; CharList_t mainmenu_app_exes; uint8_t mainmenu_app_index; + DesktopSettings desktop_settings; bool subghz_use_defaults; FrequencyList_t subghz_static_freqs; uint8_t subghz_static_index; FrequencyList_t subghz_hopper_freqs; uint8_t subghz_hopper_index; - char subghz_freq_buffer[7]; bool subghz_extend; bool subghz_bypass; RgbColor lcd_color; @@ -70,11 +79,13 @@ typedef struct { FuriString* version_tag; bool save_mainmenu_apps; + bool save_desktop; bool save_subghz_freqs; bool save_subghz; bool save_name; bool save_level; bool save_angry; + bool save_dolphin; bool save_backlight; bool save_settings; bool apply_pack; @@ -87,6 +98,7 @@ typedef enum { MomentumAppViewSubmenu, MomentumAppViewTextInput, MomentumAppViewByteInput, + MomentumAppViewNumberInput, MomentumAppViewPopup, MomentumAppViewDialogEx, } MomentumAppView; diff --git a/applications/main/momentum_app/scenes/momentum_app_scene_interface_statusbar.c b/applications/main/momentum_app/scenes/momentum_app_scene_interface_statusbar.c index 618cc5f80..6035b12c6 100644 --- a/applications/main/momentum_app/scenes/momentum_app_scene_interface_statusbar.c +++ b/applications/main/momentum_app/scenes/momentum_app_scene_interface_statusbar.c @@ -28,16 +28,14 @@ static void momentum_app_scene_interface_statusbar_battery_icon_changed(Variable variable_item_set_current_value_text(item, battery_icon_names[index]); momentum_settings.battery_icon = index; app->save_settings = true; - power_set_battery_icon_enabled(furi_record_open(RECORD_POWER), index != BatteryIconOff); - furi_record_close(RECORD_POWER); } static void momentum_app_scene_interface_statusbar_statusbar_clock_changed(VariableItem* item) { MomentumApp* app = variable_item_get_context(item); bool value = variable_item_get_current_value_index(item); variable_item_set_current_value_text(item, value ? "ON" : "OFF"); - momentum_settings.statusbar_clock = value; - app->save_settings = true; + app->desktop_settings.display_clock = value; + app->save_desktop = true; } static void momentum_app_scene_interface_statusbar_status_icons_changed(VariableItem* item) { @@ -84,8 +82,8 @@ void momentum_app_scene_interface_statusbar_on_enter(void* context) { 2, momentum_app_scene_interface_statusbar_statusbar_clock_changed, app); - variable_item_set_current_value_index(item, momentum_settings.statusbar_clock); - variable_item_set_current_value_text(item, momentum_settings.statusbar_clock ? "ON" : "OFF"); + variable_item_set_current_value_index(item, app->desktop_settings.display_clock); + variable_item_set_current_value_text(item, app->desktop_settings.display_clock ? "ON" : "OFF"); item = variable_item_list_add( var_item_list, diff --git a/applications/main/momentum_app/scenes/momentum_app_scene_misc_dolphin.c b/applications/main/momentum_app/scenes/momentum_app_scene_misc_dolphin.c index 49cbf0132..593424c4a 100644 --- a/applications/main/momentum_app/scenes/momentum_app_scene_misc_dolphin.c +++ b/applications/main/momentum_app/scenes/momentum_app_scene_misc_dolphin.c @@ -18,6 +18,7 @@ static void momentum_app_scene_misc_dolphin_dolphin_level_changed(VariableItem* snprintf(level_str, 4, "%li", app->dolphin_level); variable_item_set_current_value_text(item, level_str); app->save_level = true; + app->save_dolphin = true; } static void momentum_app_scene_misc_dolphin_dolphin_angry_changed(VariableItem* item) { @@ -27,6 +28,7 @@ static void momentum_app_scene_misc_dolphin_dolphin_angry_changed(VariableItem* snprintf(angry_str, 4, "%li", app->dolphin_angry); variable_item_set_current_value_text(item, angry_str); app->save_angry = true; + app->save_dolphin = true; } const char* const butthurt_timer_names[] = { @@ -59,7 +61,7 @@ static void momentum_app_scene_misc_dolphin_butthurt_timer_changed(VariableItem* variable_item_set_current_value_text(item, butthurt_timer_names[index]); momentum_settings.butthurt_timer = butthurt_timer_values[index]; app->save_settings = true; - app->require_reboot = true; + app->save_dolphin = true; } void momentum_app_scene_misc_dolphin_on_enter(void* context) { diff --git a/applications/main/momentum_app/scenes/momentum_app_scene_protocols_freqs_add.c b/applications/main/momentum_app/scenes/momentum_app_scene_protocols_freqs_add.c index 3481cb4fc..aa51add21 100644 --- a/applications/main/momentum_app/scenes/momentum_app_scene_protocols_freqs_add.c +++ b/applications/main/momentum_app/scenes/momentum_app_scene_protocols_freqs_add.c @@ -5,12 +5,12 @@ enum TextInputResult { TextInputResultError, }; -static void momentum_app_scene_protocols_freqs_add_text_input_callback(void* context) { +static void + momentum_app_scene_protocols_freqs_add_number_input_callback(void* context, int32_t number) { MomentumApp* app = context; - char* end; - uint32_t value = strtol(app->subghz_freq_buffer, &end, 0) * 1000; - if(*end || !furi_hal_subghz_is_frequency_valid(value)) { + uint32_t value = number * 1000; + if(!furi_hal_subghz_is_frequency_valid(value)) { view_dispatcher_send_custom_event(app->view_dispatcher, TextInputResultError); return; } @@ -27,26 +27,24 @@ static void momentum_app_scene_protocols_freqs_add_text_input_callback(void* con void momentum_app_scene_protocols_freqs_add_on_enter(void* context) { MomentumApp* app = context; - TextInput* text_input = app->text_input; + NumberInput* number_input = app->number_input; - text_input_set_header_text(text_input, "Ex: 123456 for 123.456 MHz"); + number_input_set_header_text(number_input, "Use kHz values, like 433920"); - strlcpy(app->subghz_freq_buffer, "", sizeof(app->subghz_freq_buffer)); - - text_input_set_result_callback( - text_input, - momentum_app_scene_protocols_freqs_add_text_input_callback, + number_input_set_result_callback( + number_input, + momentum_app_scene_protocols_freqs_add_number_input_callback, app, - app->subghz_freq_buffer, - sizeof(app->subghz_freq_buffer), - true); + 0, + 100000, + 999999); - view_dispatcher_switch_to_view(app->view_dispatcher, MomentumAppViewTextInput); + view_dispatcher_switch_to_view(app->view_dispatcher, MomentumAppViewNumberInput); } void callback_return(void* context) { MomentumApp* app = context; - scene_manager_previous_scene(app->scene_manager); + view_dispatcher_switch_to_view(app->view_dispatcher, MomentumAppViewNumberInput); } bool momentum_app_scene_protocols_freqs_add_on_event(void* context, SceneManagerEvent event) { @@ -60,9 +58,15 @@ bool momentum_app_scene_protocols_freqs_add_on_event(void* context, SceneManager scene_manager_previous_scene(app->scene_manager); break; case TextInputResultError: - popup_set_header(app->popup, "Invalid value!", 64, 26, AlignCenter, AlignCenter); + popup_set_header(app->popup, "Invalid frequency!", 64, 18, AlignCenter, AlignCenter); popup_set_text( - app->popup, "Frequency was not added...", 64, 40, AlignCenter, AlignCenter); + app->popup, + "Must be 281-361,\n" + "378-481, 749-962 MHz", + 64, + 40, + AlignCenter, + AlignCenter); popup_set_callback(app->popup, callback_return); popup_set_context(app->popup, app); popup_set_timeout(app->popup, 1000); diff --git a/applications/main/nfc/helpers/mf_user_dict.c b/applications/main/nfc/helpers/mf_user_dict.c index 70b111472..7f60d339e 100644 --- a/applications/main/nfc/helpers/mf_user_dict.c +++ b/applications/main/nfc/helpers/mf_user_dict.c @@ -4,7 +4,7 @@ #include #include -#define NFC_APP_FOLDER ANY_PATH("nfc") +#define NFC_APP_FOLDER EXT_PATH("nfc") #define NFC_APP_MF_CLASSIC_DICT_USER_PATH (NFC_APP_FOLDER "/assets/mf_classic_dict_user.nfc") struct MfUserDict { diff --git a/applications/main/nfc/icon.png b/applications/main/nfc/icon.png index 6bc027111..e998d291e 100644 Binary files a/applications/main/nfc/icon.png and b/applications/main/nfc/icon.png differ diff --git a/applications/main/nfc/nfc_app.c b/applications/main/nfc/nfc_app.c index 483d63c14..e61e172f0 100644 --- a/applications/main/nfc/nfc_app.c +++ b/applications/main/nfc/nfc_app.c @@ -42,7 +42,6 @@ NfcApp* nfc_app_alloc(void) { instance->view_dispatcher = view_dispatcher_alloc(); instance->scene_manager = scene_manager_alloc(&nfc_scene_handlers, instance); - view_dispatcher_enable_queue(instance->view_dispatcher); view_dispatcher_set_event_callback_context(instance->view_dispatcher, instance); view_dispatcher_set_custom_event_callback( instance->view_dispatcher, nfc_custom_event_callback); diff --git a/applications/main/nfc/nfc_app_i.h b/applications/main/nfc/nfc_app_i.h index 62917ad1d..7896d65db 100644 --- a/applications/main/nfc/nfc_app_i.h +++ b/applications/main/nfc/nfc_app_i.h @@ -67,7 +67,7 @@ #define NFC_TEXT_STORE_SIZE 128 #define NFC_BYTE_INPUT_STORE_SIZE 10 #define NFC_LOG_SIZE_MAX (1024) -#define NFC_APP_FOLDER ANY_PATH("nfc") +#define NFC_APP_FOLDER EXT_PATH("nfc") #define NFC_APP_EXTENSION ".nfc" #define NFC_APP_SHADOW_EXTENSION ".shd" #define NFC_APP_FILENAME_PREFIX "NFC" diff --git a/applications/main/subghz/application.fam b/applications/main/subghz/application.fam index f2b42b01f..15831d6e6 100644 --- a/applications/main/subghz/application.fam +++ b/applications/main/subghz/application.fam @@ -16,6 +16,7 @@ App( # "!helpers/subghz_chat.c", # "!subghz_extended_freq.c", # ], + requires=["region"], resources="resources", fap_libs=["hwdrivers"], fap_icon="icon.png", diff --git a/applications/main/subghz/icon.png b/applications/main/subghz/icon.png index 5a25fdf4e..70940ad77 100644 Binary files a/applications/main/subghz/icon.png and b/applications/main/subghz/icon.png differ diff --git a/applications/main/subghz/scenes/subghz_scene_rpc.c b/applications/main/subghz/scenes/subghz_scene_rpc.c index 2f8a1f03f..4675afaeb 100644 --- a/applications/main/subghz/scenes/subghz_scene_rpc.c +++ b/applications/main/subghz/scenes/subghz_scene_rpc.c @@ -59,7 +59,8 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) { default: //if(SubGhzTxRxStartTxStateOk) result = true; subghz_blink_start(subghz); - state = SubGhzRpcStateTx; + scene_manager_set_scene_state( + subghz->scene_manager, SubGhzSceneRpc, SubGhzRpcStateTx); break; } } @@ -71,7 +72,8 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) { subghz_blink_stop(subghz); result = true; } - state = SubGhzRpcStateIdle; + scene_manager_set_scene_state( + subghz->scene_manager, SubGhzSceneRpc, SubGhzRpcStateIdle); rpc_system_app_confirm(subghz->rpc_ctx, result); } else if(event.event == SubGhzCustomEventSceneRpcLoad) { bool result = false; diff --git a/applications/main/subghz/subghz.c b/applications/main/subghz/subghz.c index 089ffd0e9..1d86d596d 100644 --- a/applications/main/subghz/subghz.c +++ b/applications/main/subghz/subghz.c @@ -102,7 +102,6 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) { // View Dispatcher subghz->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_enable_queue(subghz->view_dispatcher); subghz->scene_manager = scene_manager_alloc(&subghz_scene_handlers, subghz); view_dispatcher_set_event_callback_context(subghz->view_dispatcher, subghz); diff --git a/applications/main/subghz/subghz_cli.c b/applications/main/subghz/subghz_cli.c index 7be313875..e53f7eb24 100644 --- a/applications/main/subghz/subghz_cli.c +++ b/applications/main/subghz/subghz_cli.c @@ -426,7 +426,7 @@ void subghz_cli_command_rx_raw(Cli* cli, FuriString* args, void* context) { // Configure radio furi_hal_subghz_reset(); - furi_hal_subghz_load_custom_preset(subghz_device_cc1101_preset_ook_650khz_async_regs); + furi_hal_subghz_load_custom_preset(subghz_device_cc1101_preset_ook_270khz_async_regs); frequency = furi_hal_subghz_set_frequency_and_path(frequency); furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); @@ -478,7 +478,7 @@ void subghz_cli_command_rx_raw(Cli* cli, FuriString* args, void* context) { void subghz_cli_command_decode_raw(Cli* cli, FuriString* args, void* context) { UNUSED(context); FuriString* file_name = furi_string_alloc(); - furi_string_set(file_name, ANY_PATH("subghz/test.sub")); + furi_string_set(file_name, EXT_PATH("subghz/test.sub")); Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); @@ -592,7 +592,7 @@ void subghz_cli_command_tx_from_file(Cli* cli, FuriString* args, void* context) UNUSED(context); FuriString* file_name; file_name = furi_string_alloc(); - furi_string_set(file_name, ANY_PATH("subghz/test.sub")); + furi_string_set(file_name, EXT_PATH("subghz/test.sub")); uint32_t repeat = 10; uint32_t device_ind = 0; // 0 - CC1101_INT, 1 - CC1101_EXT @@ -959,9 +959,7 @@ static void subghz_cli_command_chat(Cli* cli, FuriString* args) { subghz_cli_radio_device_power_off(); return; } - - // TODO - if(!furi_hal_subghz_is_tx_allowed(frequency)) { + if(!furi_hal_region_is_frequency_allowed(frequency)) { printf( "In your settings/region, only reception on this frequency (%lu) is allowed,\r\n" "the actual operation of the application is not possible\r\n ", diff --git a/applications/main/subghz/subghz_extended_freq.c b/applications/main/subghz/subghz_extended_freq.c index b4494f092..af4cd2712 100644 --- a/applications/main/subghz/subghz_extended_freq.c +++ b/applications/main/subghz/subghz_extended_freq.c @@ -1,10 +1,16 @@ #include #include #include +#include #include #include -void subghz_extended_freq() { +#define TAG "SubGhzExtendedFreq" + +static int32_t subghz_extended_freq_apply(void* context) { + UNUSED(context); + FURI_LOG_D(TAG, "Loading settings"); + bool is_extended_i = false; bool is_bypassed = false; Storage* storage = furi_record_open(RECORD_STORAGE); @@ -13,6 +19,7 @@ void subghz_extended_freq() { if(flipper_format_file_open_existing(file, "/ext/subghz/assets/extend_range.txt")) { flipper_format_read_bool(file, "use_ext_range_at_own_risk", &is_extended_i, 1); flipper_format_read_bool(file, "ignore_default_tx_region", &is_bypassed, 1); + flipper_format_file_close(file); } furi_hal_subghz_set_extended_range(is_extended_i); @@ -20,11 +27,29 @@ void subghz_extended_freq() { flipper_format_free(file); furi_record_close(RECORD_STORAGE); - - // Load external module power amp setting (TODO: move to other place) - // TODO: Disable this when external module is not CC1101 E07 - SubGhzLastSettings* last_settings = subghz_last_settings_alloc(); - subghz_last_settings_load(last_settings, 0); - - subghz_last_settings_free(last_settings); + return 0; +} + +static void subghz_extended_freq_mount_callback(const void* message, void* context) { + UNUSED(context); + const StorageEvent* event = message; + + if(event->type == StorageEventTypeCardMount) { + run_parallel(subghz_extended_freq_apply, NULL, 1024); + } +} + +void subghz_extended_freq() { + if(!furi_hal_is_normal_boot()) return; + + Storage* storage = furi_record_open(RECORD_STORAGE); + furi_pubsub_subscribe(storage_get_pubsub(storage), subghz_extended_freq_mount_callback, NULL); + + if(storage_sd_status(storage) != FSE_OK) { + FURI_LOG_D(TAG, "SD Card not ready, skipping settings"); + } else { + subghz_extended_freq_apply(NULL); + } + + furi_record_close(RECORD_STORAGE); } diff --git a/applications/main/u2f/icon.png b/applications/main/u2f/icon.png index fcd87a2ef..6f46b0e78 100644 Binary files a/applications/main/u2f/icon.png and b/applications/main/u2f/icon.png differ diff --git a/applications/main/u2f/u2f.c b/applications/main/u2f/u2f.c index 6a37769a8..0143eb245 100644 --- a/applications/main/u2f/u2f.c +++ b/applications/main/u2f/u2f.c @@ -4,7 +4,6 @@ #include #include #include -#include // for lfs_tobe32 #include #include @@ -319,6 +318,10 @@ static uint16_t u2f_register(U2fData* U2F, uint8_t* buf) { return sizeof(U2fRegisterResp) + cert_len + signature_len + 2; } +static inline uint32_t u2f_to_big_endian(uint32_t a) { + return __builtin_bswap32(a); +} + static uint16_t u2f_authenticate(U2fData* U2F, uint8_t* buf) { U2fAuthReq* req = (U2fAuthReq*)buf; U2fAuthResp* resp = (U2fAuthResp*)buf; @@ -348,7 +351,7 @@ static uint16_t u2f_authenticate(U2fData* U2F, uint8_t* buf) { U2F->user_present = false; // The 4 byte counter is represented in big endian. Increment it before use - be_u2f_counter = lfs_tobe32(U2F->counter + 1); + be_u2f_counter = u2f_to_big_endian(U2F->counter + 1); // Generate hash { diff --git a/applications/main/u2f/u2f_app.c b/applications/main/u2f/u2f_app.c index 5ca5c03dc..5612c0b1e 100644 --- a/applications/main/u2f/u2f_app.c +++ b/applications/main/u2f/u2f_app.c @@ -30,7 +30,6 @@ U2fApp* u2f_app_alloc(void) { app->view_dispatcher = view_dispatcher_alloc(); app->scene_manager = scene_manager_alloc(&u2f_scene_handlers, app); - view_dispatcher_enable_queue(app->view_dispatcher); view_dispatcher_set_event_callback_context(app->view_dispatcher, app); view_dispatcher_set_tick_event_callback( app->view_dispatcher, u2f_app_tick_event_callback, 500); diff --git a/applications/main/u2f/u2f_data.h b/applications/main/u2f/u2f_data.h index 54428acf9..41e0d9447 100644 --- a/applications/main/u2f/u2f_data.h +++ b/applications/main/u2f/u2f_data.h @@ -9,8 +9,8 @@ extern "C" { #define U2F_DATA_FOLDER EXT_PATH("u2f/") #define U2F_CERT_FILE U2F_DATA_FOLDER "assets/cert.der" #define U2F_CERT_KEY_FILE U2F_DATA_FOLDER "assets/cert_key.u2f" +#define U2F_KEY_FILE U2F_DATA_FOLDER "key.u2f" #define U2F_CNT_FILE U2F_DATA_FOLDER "cnt.u2f" -#define U2F_KEY_FILE INT_PATH(".key.u2f") bool u2f_data_check(bool cert_only); diff --git a/applications/services/bt/application.fam b/applications/services/bt/application.fam index 0113beb9b..54e197259 100644 --- a/applications/services/bt/application.fam +++ b/applications/services/bt/application.fam @@ -14,7 +14,7 @@ App( ], stack_size=1 * 1024, order=1000, - sdk_headers=["bt_service/bt.h", "bt_service/bt_keys_storage.h", "bt_settings.h"], + sdk_headers=["bt_service/bt.h", "bt_service/bt_keys_storage.h"], ) App( diff --git a/applications/services/bt/bt_cli.c b/applications/services/bt/bt_cli.c index 23cb3f3c1..8f94e1963 100644 --- a/applications/services/bt/bt_cli.c +++ b/applications/services/bt/bt_cli.c @@ -4,8 +4,8 @@ #include #include -#include "bt_settings.h" -#include "bt_service/bt_i.h" +#include "bt_service/bt.h" +#include "bt_service/bt_settings_api_i.h" #include static void bt_cli_command_hci_info(Cli* cli, FuriString* args, void* context) { @@ -185,6 +185,8 @@ static void bt_cli(Cli* cli, FuriString* args, void* context) { FuriString* cmd; cmd = furi_string_alloc(); + BtSettings bt_settings; + bt_get_settings(bt, &bt_settings); do { if(!args_read_string_and_trim(args, cmd)) { @@ -217,7 +219,7 @@ static void bt_cli(Cli* cli, FuriString* args, void* context) { bt_cli_print_usage(); } while(false); - if(bt->bt_settings.enabled) { + if(bt_settings.enabled) { furi_hal_bt_start_advertising(); } diff --git a/applications/services/bt/bt_service/bt.c b/applications/services/bt/bt_service/bt.c index 418154cfc..8188f8513 100644 --- a/applications/services/bt/bt_service/bt.c +++ b/applications/services/bt/bt_service/bt.c @@ -61,6 +61,21 @@ static void bt_pin_code_view_port_input_callback(InputEvent* event, void* contex } } +static void bt_storage_callback(const void* message, void* context) { + furi_assert(context); + Bt* bt = context; + const StorageEvent* event = message; + + if(event->type == StorageEventTypeCardMount) { + const BtMessage msg = { + .type = BtMessageTypeReloadKeysSettings, + }; + + furi_check( + furi_message_queue_put(bt->message_queue, &msg, FuriWaitForever) == FuriStatusOk); + } +} + static ViewPort* bt_pin_code_view_port_alloc(Bt* bt) { ViewPort* view_port = view_port_alloc(); view_port_draw_callback_set(view_port, bt_pin_code_view_port_draw_callback, bt); @@ -143,8 +158,6 @@ Bt* bt_alloc(void) { // Init default maximum packet size bt->max_packet_size = BLE_PROFILE_SERIAL_PACKET_SIZE_MAX; bt->current_profile = NULL; - // Load settings - bt_settings_load(&bt->bt_settings); // Keys storage bt->keys_storage = bt_keys_storage_alloc(BT_KEYS_STORAGE_PATH); // Alloc queue @@ -396,6 +409,8 @@ void bt_close_rpc_connection(Bt* bt) { static void bt_change_profile(Bt* bt, BtMessage* message) { if(furi_hal_bt_is_gatt_gap_supported()) { + bt_settings_load(&bt->bt_settings); + bt_close_rpc_connection(bt); bt_keys_storage_load(bt->keys_storage); @@ -439,6 +454,87 @@ static void bt_close_connection(Bt* bt, BtMessage* message) { if(message->lock) api_lock_unlock(message->lock); } +static void bt_apply_settings(Bt* bt) { + if(bt->bt_settings.enabled) { + furi_hal_bt_start_advertising(); + } else { + furi_hal_bt_stop_advertising(); + } +} + +static void bt_load_keys(Bt* bt) { + if(!furi_hal_bt_is_gatt_gap_supported()) { + bt_show_warning(bt, "Unsupported radio stack"); + bt->status = BtStatusUnavailable; + return; + + } else if(bt_keys_storage_is_changed(bt->keys_storage)) { + FURI_LOG_I(TAG, "Loading new keys"); + + bt_close_rpc_connection(bt); + bt_keys_storage_load(bt->keys_storage); + + bt->current_profile = NULL; + + } else { + FURI_LOG_I(TAG, "Keys unchanged"); + } +} + +static void bt_start_application(Bt* bt) { + if(!bt->current_profile) { + bt->current_profile = + furi_hal_bt_change_app(ble_profile_serial, NULL, bt_on_gap_event_callback, bt); + + if(!bt->current_profile) { + FURI_LOG_E(TAG, "BLE App start failed"); + bt->status = BtStatusUnavailable; + } + } +} + +static void bt_load_settings(Bt* bt) { + bt_settings_load(&bt->bt_settings); + bt_apply_settings(bt); +} + +static void bt_handle_get_settings(Bt* bt, BtMessage* message) { + furi_assert(message->lock); + *message->data.settings = bt->bt_settings; + api_lock_unlock(message->lock); +} + +static void bt_handle_set_settings(Bt* bt, BtMessage* message) { + furi_assert(message->lock); + bt->bt_settings = *message->data.csettings; + + bt_apply_settings(bt); + bt_settings_save(&bt->bt_settings); + + api_lock_unlock(message->lock); +} + +static void bt_handle_reload_keys_settings(Bt* bt) { + bt_load_keys(bt); + bt_start_application(bt); + bt_load_settings(bt); +} + +static void bt_init_keys_settings(Bt* bt) { + Storage* storage = furi_record_open(RECORD_STORAGE); + furi_pubsub_subscribe(storage_get_pubsub(storage), bt_storage_callback, bt); + + if(storage_sd_status(storage) != FSE_OK) { + FURI_LOG_D(TAG, "SD Card not ready, skipping settings"); + + // Just start the BLE serial application without loading the keys or settings + bt_start_application(bt); + return; + } + + bt_handle_reload_keys_settings(bt); +} + bool bt_remote_rssi(Bt* bt, uint8_t* rssi) { furi_assert(bt); @@ -465,35 +561,18 @@ int32_t bt_srv(void* p) { return 0; } - // Load keys - if(!bt_keys_storage_load(bt->keys_storage)) { - FURI_LOG_W(TAG, "Failed to load bonding keys"); - } + if(furi_hal_bt_start_radio_stack()) { + bt_init_keys_settings(bt); + furi_hal_bt_set_key_storage_change_callback(bt_on_key_storage_change_callback, bt); - // Start radio stack - if(!furi_hal_bt_start_radio_stack()) { - FURI_LOG_E(TAG, "Radio stack start failed"); - } - - if(furi_hal_bt_is_gatt_gap_supported()) { - bt->current_profile = - furi_hal_bt_start_app(ble_profile_serial, NULL, bt_on_gap_event_callback, bt); - if(!bt->current_profile) { - FURI_LOG_E(TAG, "BLE App start failed"); - } else { - if(bt->bt_settings.enabled) { - furi_hal_bt_start_advertising(); - } - furi_hal_bt_set_key_storage_change_callback(bt_on_key_storage_change_callback, bt); - } } else { - bt_show_warning(bt, "Unsupported radio stack"); - bt->status = BtStatusUnavailable; + FURI_LOG_E(TAG, "Radio stack start failed"); } furi_record_create(RECORD_BT, bt); BtMessage message; + while(1) { furi_check( furi_message_queue_get(bt->message_queue, &message, FuriWaitForever) == FuriStatusOk); @@ -523,7 +602,14 @@ int32_t bt_srv(void* p) { bt_close_connection(bt, &message); } else if(message.type == BtMessageTypeForgetBondedDevices) { bt_keys_storage_delete(bt->keys_storage); + } else if(message.type == BtMessageTypeGetSettings) { + bt_handle_get_settings(bt, &message); + } else if(message.type == BtMessageTypeSetSettings) { + bt_handle_set_settings(bt, &message); + } else if(message.type == BtMessageTypeReloadKeysSettings) { + bt_handle_reload_keys_settings(bt); } } + return 0; } diff --git a/applications/services/bt/bt_service/bt.h b/applications/services/bt/bt_service/bt.h index 84e0e573c..0f2f23c1a 100644 --- a/applications/services/bt/bt_service/bt.h +++ b/applications/services/bt/bt_service/bt.h @@ -20,11 +20,6 @@ typedef enum { BtStatusConnected, } BtStatus; -typedef struct { - uint8_t rssi; - uint32_t since; -} BtRssi; - typedef void (*BtStatusChangedCallback)(BtStatus status, void* context); /** Change BLE Profile @@ -84,6 +79,12 @@ void bt_keys_storage_set_storage_path(Bt* bt, const char* keys_storage_path); */ void bt_keys_storage_set_default_path(Bt* bt); +/** Get BLE remote RSSI value + * + * @param bt Bt instance + * + * @return true on success + */ bool bt_remote_rssi(Bt* bt, uint8_t* rssi); /** Open a new RPC connection diff --git a/applications/services/bt/bt_service/bt_api.c b/applications/services/bt/bt_service/bt_api.c index f0e792d42..39b9a099d 100644 --- a/applications/services/bt/bt_service/bt_api.c +++ b/applications/services/bt/bt_service/bt_api.c @@ -77,3 +77,39 @@ void bt_keys_storage_set_default_path(Bt* bt) { bt_keys_storage_set_file_path(bt->keys_storage, BT_KEYS_STORAGE_PATH); } + +/* + * Private API for the Settings app + */ + +void bt_get_settings(Bt* bt, BtSettings* settings) { + furi_assert(bt); + furi_assert(settings); + + BtMessage message = { + .lock = api_lock_alloc_locked(), + .type = BtMessageTypeGetSettings, + .data.settings = settings, + }; + + furi_check( + furi_message_queue_put(bt->message_queue, &message, FuriWaitForever) == FuriStatusOk); + + api_lock_wait_unlock_and_free(message.lock); +} + +void bt_set_settings(Bt* bt, const BtSettings* settings) { + furi_assert(bt); + furi_assert(settings); + + BtMessage message = { + .lock = api_lock_alloc_locked(), + .type = BtMessageTypeSetSettings, + .data.csettings = settings, + }; + + furi_check( + furi_message_queue_put(bt->message_queue, &message, FuriWaitForever) == FuriStatusOk); + + api_lock_wait_unlock_and_free(message.lock); +} diff --git a/applications/services/bt/bt_service/bt_i.h b/applications/services/bt/bt_service/bt_i.h index 933d493a9..e5578ff22 100644 --- a/applications/services/bt/bt_service/bt_i.h +++ b/applications/services/bt/bt_service/bt_i.h @@ -19,7 +19,7 @@ #include #include -#define BT_KEYS_STORAGE_PATH CFG_PATH("bt.keys") +#include "bt_keys_filename.h" typedef enum { BtMessageTypeUpdateStatus, @@ -30,6 +30,9 @@ typedef enum { BtMessageTypeSetProfile, BtMessageTypeDisconnect, BtMessageTypeForgetBondedDevices, + BtMessageTypeGetSettings, + BtMessageTypeSetSettings, + BtMessageTypeReloadKeysSettings, } BtMessageType; typedef struct { @@ -47,6 +50,8 @@ typedef union { } profile; FuriHalBleProfileParams profile_params; BtKeyStorageUpdateData key_storage_data; + BtSettings* settings; + const BtSettings* csettings; } BtMessageData; typedef struct { @@ -81,6 +86,7 @@ struct Bt { FuriEventFlag* api_event; BtStatusChangedCallback status_changed_cb; void* status_changed_ctx; + uint32_t pin; bool suppress_pin_screen; }; diff --git a/applications/services/bt/bt_service/bt_keys_filename.h b/applications/services/bt/bt_service/bt_keys_filename.h new file mode 100644 index 000000000..1c1135a29 --- /dev/null +++ b/applications/services/bt/bt_service/bt_keys_filename.h @@ -0,0 +1,5 @@ +#pragma once + +#define BT_KEYS_STORAGE_FILE_NAME ".bt.keys" + +#define BT_KEYS_STORAGE_PATH INT_PATH(BT_KEYS_STORAGE_FILE_NAME) diff --git a/applications/services/bt/bt_service/bt_keys_storage.c b/applications/services/bt/bt_service/bt_keys_storage.c index 6392c2d67..57742e8e2 100644 --- a/applications/services/bt/bt_service/bt_keys_storage.c +++ b/applications/services/bt/bt_service/bt_keys_storage.c @@ -13,6 +13,7 @@ struct BtKeysStorage { uint8_t* nvm_sram_buff; uint16_t nvm_sram_buff_size; + uint16_t current_size; FuriString* file_path; }; @@ -66,44 +67,114 @@ void bt_keys_storage_set_ram_params(BtKeysStorage* instance, uint8_t* buff, uint instance->nvm_sram_buff_size = size; } +static bool bt_keys_storage_file_exists(const char* file_path) { + Storage* storage = furi_record_open(RECORD_STORAGE); + FileInfo file_info; + const bool ret = storage_common_stat(storage, file_path, &file_info) == FSE_OK && + file_info.size != 0; + furi_record_close(RECORD_STORAGE); + return ret; +} + +static bool bt_keys_storage_validate_file(const char* file_path, size_t* payload_size) { + uint8_t magic, version; + size_t size; + + if(!saved_struct_get_metadata(file_path, &magic, &version, &size)) { + FURI_LOG_E(TAG, "Failed to get metadata"); + return false; + + } else if(magic != BT_KEYS_STORAGE_MAGIC || version != BT_KEYS_STORAGE_VERSION) { + FURI_LOG_E(TAG, "File version mismatch"); + return false; + } + + *payload_size = size; + return true; +} + +bool bt_keys_storage_is_changed(BtKeysStorage* instance) { + furi_assert(instance); + + bool is_changed = false; + uint8_t* data_buffer = NULL; + + do { + const char* file_path = furi_string_get_cstr(instance->file_path); + size_t payload_size; + + if(!bt_keys_storage_file_exists(file_path)) { + FURI_LOG_W(TAG, "Missing or empty file"); + break; + + } else if(!bt_keys_storage_validate_file(file_path, &payload_size)) { + FURI_LOG_E(TAG, "Invalid or corrupted file"); + break; + } + + data_buffer = malloc(payload_size); + + const bool data_loaded = saved_struct_load( + file_path, data_buffer, payload_size, BT_KEYS_STORAGE_MAGIC, BT_KEYS_STORAGE_VERSION); + + if(!data_loaded) { + FURI_LOG_E(TAG, "Failed to load file"); + break; + + } else if(payload_size == instance->current_size) { + furi_hal_bt_nvm_sram_sem_acquire(); + is_changed = memcmp(data_buffer, instance->nvm_sram_buff, payload_size); + furi_hal_bt_nvm_sram_sem_release(); + + } else { + FURI_LOG_D(TAG, "Size mismatch"); + is_changed = true; + } + } while(false); + + if(data_buffer) { + free(data_buffer); + } + + return is_changed; +} + bool bt_keys_storage_load(BtKeysStorage* instance) { furi_assert(instance); bool loaded = false; + do { + const char* file_path = furi_string_get_cstr(instance->file_path); + // Get payload size - uint8_t magic = 0, version = 0; - size_t payload_size = 0; - if(!saved_struct_get_metadata( - furi_string_get_cstr(instance->file_path), &magic, &version, &payload_size)) { - FURI_LOG_E(TAG, "Failed to read payload size"); + size_t payload_size; + if(!bt_keys_storage_validate_file(file_path, &payload_size)) { + FURI_LOG_E(TAG, "Invalid or corrupted file"); break; - } - if(magic != BT_KEYS_STORAGE_MAGIC || version != BT_KEYS_STORAGE_VERSION) { - FURI_LOG_E(TAG, "Saved data version is mismatched"); - break; - } - - if(payload_size > instance->nvm_sram_buff_size) { - FURI_LOG_E(TAG, "Saved data doesn't fit ram buffer"); + } else if(payload_size > instance->nvm_sram_buff_size) { + FURI_LOG_E(TAG, "NVM RAM buffer overflow"); break; } // Load saved data to ram furi_hal_bt_nvm_sram_sem_acquire(); - bool data_loaded = saved_struct_load( - furi_string_get_cstr(instance->file_path), + const bool data_loaded = saved_struct_load( + file_path, instance->nvm_sram_buff, payload_size, BT_KEYS_STORAGE_MAGIC, BT_KEYS_STORAGE_VERSION); furi_hal_bt_nvm_sram_sem_release(); + if(!data_loaded) { - FURI_LOG_E(TAG, "Failed to load struct"); + FURI_LOG_E(TAG, "Failed to load file"); break; } + instance->current_size = payload_size; + loaded = true; } while(false); @@ -130,6 +201,8 @@ bool bt_keys_storage_update(BtKeysStorage* instance, uint8_t* start_addr, uint32 break; } + instance->current_size = new_size; + furi_hal_bt_nvm_sram_sem_acquire(); bool data_updated = saved_struct_save( furi_string_get_cstr(instance->file_path), @@ -138,10 +211,12 @@ bool bt_keys_storage_update(BtKeysStorage* instance, uint8_t* start_addr, uint32 BT_KEYS_STORAGE_MAGIC, BT_KEYS_STORAGE_VERSION); furi_hal_bt_nvm_sram_sem_release(); + if(!data_updated) { FURI_LOG_E(TAG, "Failed to update key storage"); break; } + updated = true; } while(false); diff --git a/applications/services/bt/bt_service/bt_keys_storage.h b/applications/services/bt/bt_service/bt_keys_storage.h index 587dd570d..b7a127035 100644 --- a/applications/services/bt/bt_service/bt_keys_storage.h +++ b/applications/services/bt/bt_service/bt_keys_storage.h @@ -17,6 +17,8 @@ void bt_keys_storage_set_file_path(BtKeysStorage* instance, const char* path); void bt_keys_storage_set_ram_params(BtKeysStorage* instance, uint8_t* buff, uint16_t size); +bool bt_keys_storage_is_changed(BtKeysStorage* instance); + bool bt_keys_storage_load(BtKeysStorage* instance); bool bt_keys_storage_update(BtKeysStorage* instance, uint8_t* start_addr, uint32_t size); diff --git a/applications/services/bt/bt_service/bt_settings_api_i.h b/applications/services/bt/bt_service/bt_settings_api_i.h new file mode 100644 index 000000000..441295893 --- /dev/null +++ b/applications/services/bt/bt_service/bt_settings_api_i.h @@ -0,0 +1,8 @@ +#pragma once + +#include "bt.h" +#include "../bt_settings.h" + +void bt_get_settings(Bt* bt, BtSettings* settings); + +void bt_set_settings(Bt* bt, const BtSettings* settings); diff --git a/applications/services/bt/bt_settings.c b/applications/services/bt/bt_settings.c index 77ca11460..04cec565a 100644 --- a/applications/services/bt/bt_settings.c +++ b/applications/services/bt/bt_settings.c @@ -1,22 +1,35 @@ #include "bt_settings.h" +#include "bt_settings_filename.h" #include -#include #include +#include + +#define TAG "BtSettings" #define BT_SETTINGS_VERSION (0) #define BT_SETTINGS_MAGIC (0x19) -bool bt_settings_load(BtSettings* bt_settings) { +void bt_settings_load(BtSettings* bt_settings) { furi_assert(bt_settings); - return saved_struct_load( + const bool success = saved_struct_load( BT_SETTINGS_PATH, bt_settings, sizeof(BtSettings), BT_SETTINGS_MAGIC, BT_SETTINGS_VERSION); + + if(!success) { + FURI_LOG_W(TAG, "Failed to load settings, using defaults"); + memset(bt_settings, 0, sizeof(BtSettings)); + // bt_settings_save(bt_settings); + } } -bool bt_settings_save(const BtSettings* bt_settings) { +void bt_settings_save(const BtSettings* bt_settings) { furi_assert(bt_settings); - return saved_struct_save( + const bool success = saved_struct_save( BT_SETTINGS_PATH, bt_settings, sizeof(BtSettings), BT_SETTINGS_MAGIC, BT_SETTINGS_VERSION); + + if(!success) { + FURI_LOG_E(TAG, "Failed to save settings"); + } } diff --git a/applications/services/bt/bt_settings.h b/applications/services/bt/bt_settings.h index 002a28e7a..c63220abb 100644 --- a/applications/services/bt/bt_settings.h +++ b/applications/services/bt/bt_settings.h @@ -1,21 +1,18 @@ #pragma once -#include #include #ifdef __cplusplus extern "C" { #endif -#define BT_SETTINGS_PATH CFG_PATH("bt.settings") - typedef struct { bool enabled; } BtSettings; -bool bt_settings_load(BtSettings* bt_settings); +void bt_settings_load(BtSettings* bt_settings); -bool bt_settings_save(const BtSettings* bt_settings); +void bt_settings_save(const BtSettings* bt_settings); #ifdef __cplusplus } diff --git a/applications/services/bt/bt_settings_filename.h b/applications/services/bt/bt_settings_filename.h new file mode 100644 index 000000000..f26f969a4 --- /dev/null +++ b/applications/services/bt/bt_settings_filename.h @@ -0,0 +1,5 @@ +#pragma once + +#define BT_SETTINGS_FILE_NAME ".bt.settings" + +#define BT_SETTINGS_PATH INT_PATH(BT_SETTINGS_FILE_NAME) diff --git a/applications/services/desktop/animations/animation_manager.c b/applications/services/desktop/animations/animation_manager.c index cac926460..a42d938cd 100644 --- a/applications/services/desktop/animations/animation_manager.c +++ b/applications/services/desktop/animations/animation_manager.c @@ -6,7 +6,6 @@ #include #include #include -#include #include "views/bubble_animation_view.h" #include "views/one_shot_animation_view.h" @@ -68,8 +67,7 @@ static void animation_manager_start_new_idle(AnimationManager* animation_manager static bool animation_manager_check_blocking(AnimationManager* animation_manager); static bool animation_manager_is_valid_idle_animation( const StorageAnimationManifestInfo* info, - const DolphinStats* stats, - const bool unlock); + const DolphinStats* stats); static void animation_manager_switch_to_one_shot_view(AnimationManager* animation_manager); static void animation_manager_switch_to_animation_view(AnimationManager* animation_manager); @@ -99,7 +97,7 @@ void animation_manager_set_interact_callback( animation_manager->interact_callback = callback; } -static void animation_manager_check_blocking_callback(const void* message, void* context) { +static void animation_manager_storage_callback(const void* message, void* context) { const StorageEvent* storage_event = message; switch(storage_event->type) { @@ -118,6 +116,22 @@ static void animation_manager_check_blocking_callback(const void* message, void* } } +static void animation_manager_dolphin_callback(const void* message, void* context) { + const DolphinPubsubEvent* dolphin_event = message; + + switch(*dolphin_event) { + case DolphinPubsubEventUpdate: + furi_assert(context); + AnimationManager* animation_manager = context; + if(animation_manager->check_blocking_callback) { + animation_manager->check_blocking_callback(animation_manager->context); + } + break; + default: + break; + } +} + static void animation_manager_timer_callback(void* context) { furi_assert(context); AnimationManager* animation_manager = context; @@ -148,8 +162,7 @@ void animation_manager_check_blocking_process(AnimationManager* animation_manage const StorageAnimationManifestInfo* manifest_info = animation_storage_get_meta(animation_manager->current_animation); - bool valid = animation_manager_is_valid_idle_animation( - manifest_info, &stats, momentum_settings.unlock_anims); + bool valid = animation_manager_is_valid_idle_animation(manifest_info, &stats); if(!valid) { animation_manager_start_new_idle(animation_manager); @@ -299,12 +312,12 @@ AnimationManager* animation_manager_alloc(void) { Storage* storage = furi_record_open(RECORD_STORAGE); animation_manager->pubsub_subscription_storage = furi_pubsub_subscribe( - storage_get_pubsub(storage), animation_manager_check_blocking_callback, animation_manager); + storage_get_pubsub(storage), animation_manager_storage_callback, animation_manager); furi_record_close(RECORD_STORAGE); Dolphin* dolphin = furi_record_open(RECORD_DOLPHIN); animation_manager->pubsub_subscription_dolphin = furi_pubsub_subscribe( - dolphin_get_pubsub(dolphin), animation_manager_check_blocking_callback, animation_manager); + dolphin_get_pubsub(dolphin), animation_manager_dolphin_callback, animation_manager); furi_record_close(RECORD_DOLPHIN); animation_manager->blocking_shown_sd_ok = true; @@ -343,8 +356,7 @@ View* animation_manager_get_animation_view(AnimationManager* animation_manager) static bool animation_manager_is_valid_idle_animation( const StorageAnimationManifestInfo* info, - const DolphinStats* stats, - const bool unlock) { + const DolphinStats* stats) { furi_assert(info); furi_assert(info->name); @@ -364,7 +376,7 @@ static bool animation_manager_is_valid_idle_animation( result = (sd_status == FSE_NOT_READY); } - if(!unlock) { + if(!momentum_settings.unlock_anims) { if((stats->butthurt < info->min_butthurt) || (stats->butthurt > info->max_butthurt)) { result = false; } @@ -394,13 +406,12 @@ static StorageAnimation* uint32_t whole_weight = 0; // Filter valid animations - bool unlock = momentum_settings.unlock_anims; StorageAnimationList_it_t it; for(StorageAnimationList_it(it, animation_list); !StorageAnimationList_end_p(it);) { StorageAnimation* storage_animation = *StorageAnimationList_ref(it); const StorageAnimationManifestInfo* manifest_info = animation_storage_get_meta(storage_animation); - bool valid = animation_manager_is_valid_idle_animation(manifest_info, &stats, unlock); + bool valid = animation_manager_is_valid_idle_animation(manifest_info, &stats); if(strcmp(manifest_info->name, HARDCODED_ANIMATION_NAME) == 0) { // Dont pick error anim randomly @@ -546,8 +557,7 @@ void animation_manager_load_and_continue_animation(AnimationManager* animation_m furi_record_close(RECORD_DOLPHIN); const StorageAnimationManifestInfo* manifest_info = animation_storage_get_meta(restore_animation); - bool valid = animation_manager_is_valid_idle_animation( - manifest_info, &stats, momentum_settings.unlock_anims); + bool valid = animation_manager_is_valid_idle_animation(manifest_info, &stats); // Restore only if anim is valid and not the error anim if(valid && strcmp(manifest_info->name, HARDCODED_ANIMATION_NAME) != 0) { animation_manager_replace_current_animation( @@ -559,11 +569,10 @@ void animation_manager_load_and_continue_animation(AnimationManager* animation_m animation_manager->idle_animation_timer, animation_manager->freezed_animation_time_left); } else { - const BubbleAnimation* bubble_animation = - animation_storage_get_bubble_animation( - animation_manager->current_animation); + const BubbleAnimation* animation = animation_storage_get_bubble_animation( + animation_manager->current_animation); int32_t duration = (momentum_settings.cycle_anims == 0) ? - (bubble_animation->duration) : + (animation->duration) : (momentum_settings.cycle_anims); furi_timer_start( animation_manager->idle_animation_timer, diff --git a/applications/services/desktop/animations/animation_storage.c b/applications/services/desktop/animations/animation_storage.c index dbfc9374d..ec3289473 100644 --- a/applications/services/desktop/animations/animation_storage.c +++ b/applications/services/desktop/animations/animation_storage.c @@ -57,6 +57,7 @@ static bool animation_storage_load_single_manifest_info( const char* name) { furi_assert(manifest_info); animation_handler_select_manifest(); + bool result = false; Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* file = flipper_format_file_alloc(storage); diff --git a/applications/services/desktop/application.fam b/applications/services/desktop/application.fam index 1e9de3d70..da6e2b802 100644 --- a/applications/services/desktop/application.fam +++ b/applications/services/desktop/application.fam @@ -14,5 +14,4 @@ App( conflicts=["updater"], stack_size=2 * 1024, order=60, - sdk_headers=["desktop_settings.h"], ) diff --git a/applications/services/desktop/desktop.c b/applications/services/desktop/desktop.c index 84f7121b0..9e1bdc4b3 100644 --- a/applications/services/desktop/desktop.c +++ b/applications/services/desktop/desktop.c @@ -1,32 +1,25 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "desktop_i.h" + #include #include -#include -#include -#include -#include "animations/animation_manager.h" -#include "desktop/scenes/desktop_scene.h" -#include "desktop/scenes/desktop_scene_i.h" -#include "desktop/views/desktop_view_locked.h" -#include "desktop/views/desktop_view_pin_input.h" -#include "desktop/views/desktop_view_pin_timeout.h" -#include "desktop_i.h" -#include "helpers/pin.h" +#include + +#include +#include +#include + +#include + +#include "scenes/desktop_scene.h" +#include "scenes/desktop_scene_locked.h" #define TAG "Desktop" static void desktop_auto_lock_arm(Desktop*); static void desktop_auto_lock_inhibit(Desktop*); static void desktop_start_auto_lock_timer(Desktop*); +static void desktop_apply_settings(Desktop*); static void desktop_loader_callback(const void* message, void* context) { furi_assert(context); @@ -43,6 +36,16 @@ static void desktop_loader_callback(const void* message, void* context) { } } +static void desktop_storage_callback(const void* message, void* context) { + furi_assert(context); + Desktop* desktop = context; + const StorageEvent* event = message; + + if(event->type == StorageEventTypeCardMount) { + view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopGlobalReloadSettings); + } +} + static void desktop_lock_icon_draw_callback(Canvas* canvas, void* context) { UNUSED(context); furi_assert(canvas); @@ -70,13 +73,13 @@ static void desktop_clock_reconfigure(Desktop* desktop) { desktop_clock_update(desktop); - if(momentum_settings.statusbar_clock) { + if(desktop->settings.display_clock) { furi_timer_start(desktop->update_clock_timer, furi_ms_to_ticks(1000)); } else { furi_timer_stop(desktop->update_clock_timer); } - view_port_enabled_set(desktop->clock_viewport, momentum_settings.statusbar_clock); + view_port_enabled_set(desktop->clock_viewport, desktop->settings.display_clock); } static void desktop_clock_draw_callback(Canvas* canvas, void* context) { @@ -117,27 +120,40 @@ static bool desktop_custom_event_callback(void* context, uint32_t event) { furi_assert(context); Desktop* desktop = (Desktop*)context; - switch(event) { - case DesktopGlobalBeforeAppStarted: + if(event == DesktopGlobalBeforeAppStarted) { if(animation_manager_is_animation_loaded(desktop->animation_manager)) { animation_manager_unload_and_stall_animation(desktop->animation_manager); } + desktop_auto_lock_inhibit(desktop); + desktop->app_running = true; + furi_semaphore_release(desktop->animation_semaphore); - return true; - case DesktopGlobalAfterAppFinished: + + } else if(event == DesktopGlobalAfterAppFinished) { animation_manager_load_and_continue_animation(desktop->animation_manager); - desktop_clock_reconfigure(desktop); desktop_auto_lock_arm(desktop); - return true; - case DesktopGlobalAutoLock: - if(!loader_is_locked(desktop->loader) && !desktop->locked) { + desktop->app_running = false; + + } else if(event == DesktopGlobalAutoLock) { + if(!desktop->app_running && !desktop->locked) { desktop_lock(desktop, desktop->settings.auto_lock_with_pin); } - return true; + + } else if(event == DesktopGlobalSaveSettings) { + desktop_settings_save(&desktop->settings); + desktop_apply_settings(desktop); + + } else if(event == DesktopGlobalReloadSettings) { + desktop_keybinds_migrate(desktop); + desktop_settings_load(&desktop->settings); + desktop_apply_settings(desktop); + + } else { + return scene_manager_handle_custom_event(desktop->scene_manager, event); } - return scene_manager_handle_custom_event(desktop->scene_manager, event); + return true; } static bool desktop_back_event_callback(void* context) { @@ -205,87 +221,41 @@ static void desktop_clock_timer_callback(void* context) { furi_assert(context); Desktop* desktop = context; - if(gui_active_view_port_count(desktop->gui, GuiLayerStatusBarLeft) < 6) { + const bool clock_enabled = gui_active_view_port_count(desktop->gui, GuiLayerStatusBarLeft) < 6; + + if(clock_enabled) { desktop_clock_update(desktop); - - view_port_enabled_set(desktop->clock_viewport, true); - } else { - view_port_enabled_set(desktop->clock_viewport, false); } + + view_port_enabled_set(desktop->clock_viewport, clock_enabled); } -void desktop_lock(Desktop* desktop, bool pin_lock) { - furi_assert(!desktop->locked); - - pin_lock = pin_lock && desktop_pin_is_valid(&desktop->settings.pin_code); - if(!furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock)) { - furi_hal_rtc_set_pin_fails(0); - } - if(pin_lock) { - furi_hal_rtc_set_flag(FuriHalRtcFlagLock); - Cli* cli = furi_record_open(RECORD_CLI); - cli_session_close(cli); - furi_record_close(RECORD_CLI); - if(!momentum_settings.allow_locked_rpc_commands) { - Bt* bt = furi_record_open(RECORD_BT); - bt_close_rpc_connection(bt); - furi_record_close(RECORD_BT); - } - } - - desktop_auto_lock_inhibit(desktop); - scene_manager_set_scene_state( - desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER); - scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked); - - DesktopStatus status = {.locked = true}; - furi_pubsub_publish(desktop->status_pubsub, &status); - - desktop->locked = true; -} - -void desktop_unlock(Desktop* desktop) { - furi_assert(desktop->locked); - - view_port_enabled_set(desktop->lock_icon_viewport, false); - Gui* gui = furi_record_open(RECORD_GUI); - gui_set_lockdown(gui, false); - furi_record_close(RECORD_GUI); - desktop_view_locked_unlock(desktop->locked_view); - scene_manager_search_and_switch_to_previous_scene(desktop->scene_manager, DesktopSceneMain); - desktop_auto_lock_arm(desktop); - - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock)) { - furi_hal_rtc_reset_flag(FuriHalRtcFlagLock); - furi_hal_rtc_set_pin_fails(0); - Cli* cli = furi_record_open(RECORD_CLI); - cli_session_open(cli, &cli_vcp); - furi_record_close(RECORD_CLI); - } - - Bt* bt = furi_record_open(RECORD_BT); - bt_open_rpc_connection(bt); - furi_record_close(RECORD_BT); - - DesktopStatus status = {.locked = false}; - furi_pubsub_publish(desktop->status_pubsub, &status); - - desktop->locked = false; -} - -void desktop_set_stealth_mode_state(Desktop* desktop, bool enabled) { +static void desktop_apply_settings(Desktop* desktop) { desktop->in_transition = true; - if(enabled) { - furi_hal_rtc_set_flag(FuriHalRtcFlagStealthMode); - } else { - furi_hal_rtc_reset_flag(FuriHalRtcFlagStealthMode); + + desktop_clock_reconfigure(desktop); + + if(!desktop->app_running && !desktop->locked) { + desktop_auto_lock_arm(desktop); } - desktop_lock_menu_set_stealth_mode_state(desktop->lock_menu, enabled); - view_port_enabled_set(desktop->stealth_mode_icon_viewport, enabled); + desktop->in_transition = false; } -Desktop* desktop_alloc(void) { +static void desktop_init_settings(Desktop* desktop) { + furi_pubsub_subscribe(storage_get_pubsub(desktop->storage), desktop_storage_callback, desktop); + + if(storage_sd_status(desktop->storage) != FSE_OK) { + FURI_LOG_D(TAG, "SD Card not ready, skipping settings"); + return; + } + + desktop_keybinds_migrate(desktop); + desktop_settings_load(&desktop->settings); + desktop_apply_settings(desktop); +} + +static Desktop* desktop_alloc(void) { Desktop* desktop = malloc(sizeof(Desktop)); desktop->animation_semaphore = furi_semaphore_alloc(1, 0); @@ -295,7 +265,6 @@ Desktop* desktop_alloc(void) { desktop->view_dispatcher = view_dispatcher_alloc(); desktop->scene_manager = scene_manager_alloc(&desktop_scene_handlers, desktop); - view_dispatcher_enable_queue(desktop->view_dispatcher); view_dispatcher_attach_to_gui( desktop->view_dispatcher, desktop->gui, ViewDispatcherTypeDesktop); view_dispatcher_set_tick_event_callback( @@ -383,16 +352,14 @@ Desktop* desktop_alloc(void) { } gui_add_view_port(desktop->gui, desktop->stealth_mode_icon_viewport, GuiLayerStatusBarLeft); + // Unload animations before starting an application desktop->loader = furi_record_open(RECORD_LOADER); + furi_pubsub_subscribe(loader_get_pubsub(desktop->loader), desktop_loader_callback, desktop); + desktop->storage = furi_record_open(RECORD_STORAGE); desktop->notification = furi_record_open(RECORD_NOTIFICATION); - desktop->app_start_stop_subscription = furi_pubsub_subscribe( - loader_get_pubsub(desktop->loader), desktop_loader_callback, desktop); - desktop->input_events_pubsub = furi_record_open(RECORD_INPUT_EVENTS); - desktop->input_events_subscription = NULL; desktop->ascii_events_pubsub = furi_record_open(RECORD_ASCII_EVENTS); - desktop->ascii_events_subscription = NULL; desktop->auto_lock_timer = furi_timer_alloc(desktop_auto_lock_timer_callback, FuriTimerTypeOnce, desktop); @@ -402,19 +369,97 @@ Desktop* desktop_alloc(void) { desktop->update_clock_timer = furi_timer_alloc(desktop_clock_timer_callback, FuriTimerTypePeriodic, desktop); + desktop->app_running = loader_is_locked(desktop->loader); + furi_record_create(RECORD_DESKTOP, desktop); return desktop; } -static bool desktop_check_file_flag(const char* flag_path) { - Storage* storage = furi_record_open(RECORD_STORAGE); - bool exists = storage_common_stat(storage, flag_path, NULL) == FSE_OK; - furi_record_close(RECORD_STORAGE); +/* + * Private API + */ - return exists; +void desktop_lock(Desktop* desktop, bool with_pin) { + furi_assert(!desktop->locked); + + with_pin = with_pin && desktop_pin_code_is_set(); + if(!furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock)) { + furi_hal_rtc_set_pin_fails(0); + } + + if(with_pin) { + furi_hal_rtc_set_flag(FuriHalRtcFlagLock); + if(!momentum_settings.allow_locked_rpc_commands) { + Cli* cli = furi_record_open(RECORD_CLI); + cli_session_close(cli); + furi_record_close(RECORD_CLI); + Bt* bt = furi_record_open(RECORD_BT); + bt_close_rpc_connection(bt); + furi_record_close(RECORD_BT); + } + } + + desktop_auto_lock_inhibit(desktop); + scene_manager_set_scene_state( + desktop->scene_manager, DesktopSceneLocked, DesktopSceneLockedStateFirstEnter); + scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked); + + DesktopStatus status = {.locked = true}; + furi_pubsub_publish(desktop->status_pubsub, &status); + + desktop->locked = true; } +void desktop_unlock(Desktop* desktop) { + furi_assert(desktop->locked); + + view_port_enabled_set(desktop->lock_icon_viewport, false); + Gui* gui = furi_record_open(RECORD_GUI); + gui_set_lockdown(gui, false); + furi_record_close(RECORD_GUI); + desktop_view_locked_unlock(desktop->locked_view); + scene_manager_search_and_switch_to_previous_scene(desktop->scene_manager, DesktopSceneMain); + desktop_auto_lock_arm(desktop); + bool with_pin = furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock); + furi_hal_rtc_reset_flag(FuriHalRtcFlagLock); + furi_hal_rtc_set_pin_fails(0); + + if(with_pin) { + Cli* cli = furi_record_open(RECORD_CLI); + cli_session_open(cli, &cli_vcp); + furi_record_close(RECORD_CLI); + Bt* bt = furi_record_open(RECORD_BT); + bt_open_rpc_connection(bt); + furi_record_close(RECORD_BT); + } + + DesktopStatus status = {.locked = false}; + furi_pubsub_publish(desktop->status_pubsub, &status); + + desktop->locked = false; +} + +void desktop_set_stealth_mode_state(Desktop* desktop, bool enabled) { + desktop->in_transition = true; + + if(enabled) { + furi_hal_rtc_set_flag(FuriHalRtcFlagStealthMode); + } else { + furi_hal_rtc_reset_flag(FuriHalRtcFlagStealthMode); + } + + desktop_lock_menu_set_stealth_mode_state(desktop->lock_menu, enabled); + + view_port_enabled_set(desktop->stealth_mode_icon_viewport, enabled); + + desktop->in_transition = false; +} + +/* + * Public API + */ + bool desktop_api_is_locked(Desktop* instance) { furi_assert(instance); return furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock); @@ -430,55 +475,30 @@ FuriPubSub* desktop_api_get_status_pubsub(Desktop* instance) { return instance->status_pubsub; } -static const KeybindType keybind_types[] = { - [InputTypeShort] = KeybindTypePress, - [InputTypeLong] = KeybindTypeHold, -}; - -static const KeybindKey keybind_keys[] = { - [InputKeyUp] = KeybindKeyUp, - [InputKeyDown] = KeybindKeyDown, - [InputKeyRight] = KeybindKeyRight, - [InputKeyLeft] = KeybindKeyLeft, -}; - -void desktop_run_keybind(Desktop* instance, InputType _type, InputKey _key) { - if(_type != InputTypeShort && _type != InputTypeLong) return; - if(_key != InputKeyUp && _key != InputKeyDown && _key != InputKeyRight && _key != InputKeyLeft) - return; - - KeybindType type = keybind_types[_type]; - KeybindKey key = keybind_keys[_key]; - const char* keybind = instance->keybinds[type][key].data; - if(!strnlen(keybind, MAX_KEYBIND_LENGTH)) return; - - if(!strncmp(keybind, "Apps Menu", MAX_KEYBIND_LENGTH)) { - loader_start_detached_with_gui_error(instance->loader, LOADER_APPLICATIONS_NAME, NULL); - } else if(!strncmp(keybind, "Archive", MAX_KEYBIND_LENGTH)) { - view_dispatcher_send_custom_event(instance->view_dispatcher, DesktopMainEventOpenArchive); - } else if(!strncmp(keybind, "Clock", MAX_KEYBIND_LENGTH)) { - loader_start_detached_with_gui_error( - instance->loader, EXT_PATH("apps/Tools/nightstand.fap"), ""); - } else if(!strncmp(keybind, "Device Info", MAX_KEYBIND_LENGTH)) { - loader_start_detached_with_gui_error(instance->loader, "Power", "about_battery"); - } else if(!strncmp(keybind, "Lock Menu", MAX_KEYBIND_LENGTH)) { - view_dispatcher_send_custom_event(instance->view_dispatcher, DesktopMainEventOpenLockMenu); - } else if(!strncmp(keybind, "Lock Keypad", MAX_KEYBIND_LENGTH)) { - view_dispatcher_send_custom_event(instance->view_dispatcher, DesktopMainEventLockKeypad); - } else if(!strncmp(keybind, "Lock with PIN", MAX_KEYBIND_LENGTH)) { - view_dispatcher_send_custom_event(instance->view_dispatcher, DesktopMainEventLockWithPin); - } else if(!strncmp(keybind, "Wipe Device", MAX_KEYBIND_LENGTH)) { - loader_start_detached_with_gui_error(instance->loader, "Storage", "wipe"); - } else { - if(storage_common_exists(furi_record_open(RECORD_STORAGE), keybind)) { - run_with_default_app(keybind); - } else { - loader_start_detached_with_gui_error(instance->loader, keybind, NULL); - } - furi_record_close(RECORD_STORAGE); - } +void desktop_api_reload_settings(Desktop* instance) { + furi_assert(instance); + view_dispatcher_send_custom_event(instance->view_dispatcher, DesktopGlobalReloadSettings); } +void desktop_api_get_settings(Desktop* instance, DesktopSettings* settings) { + furi_assert(instance); + furi_assert(settings); + + *settings = instance->settings; +} + +void desktop_api_set_settings(Desktop* instance, const DesktopSettings* settings) { + furi_assert(instance); + furi_assert(settings); + + instance->settings = *settings; + view_dispatcher_send_custom_event(instance->view_dispatcher, DesktopGlobalSaveSettings); +} + +/* + * Application thread + */ + int32_t desktop_srv(void* p) { UNUSED(p); @@ -491,31 +511,15 @@ int32_t desktop_srv(void* p) { Desktop* desktop = desktop_alloc(); - bool ok = DESKTOP_SETTINGS_LOAD(&desktop->settings); - if(ok && desktop->settings.pin_code.length) { - ok = desktop_pin_is_valid(&desktop->settings.pin_code); - } - if(!ok) { - memset(&desktop->settings, 0, sizeof(desktop->settings)); - furi_hal_rtc_reset_flag(FuriHalRtcFlagLock); - furi_hal_rtc_set_pin_fails(0); - } - - DESKTOP_KEYBINDS_LOAD(&desktop->keybinds, sizeof(desktop->keybinds)); - - desktop_clock_reconfigure(desktop); + desktop_init_settings(desktop); scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain); if(momentum_settings.lock_on_boot || furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock)) { desktop_lock(desktop, true); - } else { - if(!loader_is_locked(desktop->loader)) { - desktop_auto_lock_arm(desktop); - } } - if(desktop_check_file_flag(SLIDESHOW_FS_PATH)) { + if(storage_file_exists(desktop->storage, SLIDESHOW_FS_PATH)) { scene_manager_next_scene(desktop->scene_manager, DesktopSceneSlideshow); } @@ -539,14 +543,12 @@ int32_t desktop_srv(void* p) { } // Special case: autostart application is already running - if(loader_is_locked(desktop->loader) && - animation_manager_is_animation_loaded(desktop->animation_manager)) { + if(desktop->app_running && animation_manager_is_animation_loaded(desktop->animation_manager)) { animation_manager_unload_and_stall_animation(desktop->animation_manager); } view_dispatcher_run(desktop->view_dispatcher); - furi_crash("That was unexpected"); - + // Should never get here (a service thread will crash automatically if it returns) return 0; } diff --git a/applications/services/desktop/desktop.h b/applications/services/desktop/desktop.h index 4c7551f5c..9768a59cf 100644 --- a/applications/services/desktop/desktop.h +++ b/applications/services/desktop/desktop.h @@ -3,18 +3,22 @@ #include #include -typedef struct Desktop Desktop; +#include "desktop_settings.h" #define RECORD_DESKTOP "desktop" -bool desktop_api_is_locked(Desktop* instance); - -void desktop_api_unlock(Desktop* instance); +typedef struct Desktop Desktop; typedef struct { bool locked; } DesktopStatus; +bool desktop_api_is_locked(Desktop* instance); + +void desktop_api_unlock(Desktop* instance); + FuriPubSub* desktop_api_get_status_pubsub(Desktop* instance); -void desktop_run_keybind(Desktop* instance, InputType _type, InputKey _key); +void desktop_api_get_settings(Desktop* instance, DesktopSettings* settings); + +void desktop_api_set_settings(Desktop* instance, const DesktopSettings* settings); diff --git a/applications/services/desktop/desktop_i.h b/applications/services/desktop/desktop_i.h index f6a649f8c..91b7060ce 100644 --- a/applications/services/desktop/desktop_i.h +++ b/applications/services/desktop/desktop_i.h @@ -1,6 +1,9 @@ #pragma once #include "desktop.h" +#include "desktop_settings.h" +#include "desktop_keybinds.h" + #include "animations/animation_manager.h" #include "views/desktop_view_pin_timeout.h" #include "views/desktop_view_pin_input.h" @@ -9,9 +12,7 @@ #include "views/desktop_view_lock_menu.h" #include "views/desktop_view_debug.h" #include "views/desktop_view_slideshow.h" -#include -#include #include #include #include @@ -42,9 +43,8 @@ typedef struct { } DesktopClock; struct Desktop { - // Scene FuriThread* scene_thread; - // GUI + Gui* gui; ViewDispatcher* view_dispatcher; SceneManager* scene_manager; @@ -56,47 +56,41 @@ struct Desktop { DesktopMainView* main_view; DesktopViewPinTimeout* pin_timeout_view; DesktopSlideshowView* slideshow_view; + DesktopViewPinInput* pin_input_view; ViewStack* main_view_stack; ViewStack* locked_view_stack; - DesktopSettings settings; - DesktopViewPinInput* pin_input_view; - ViewPort* lock_icon_viewport; ViewPort* _dummy_mode_icon_viewport; // Unused, kept for compatibility ViewPort* clock_viewport; ViewPort* stealth_mode_icon_viewport; - AnimationManager* animation_manager; - Loader* loader; + Storage* storage; NotificationApp* notification; - FuriPubSubSubscription* app_start_stop_subscription; + FuriPubSub* status_pubsub; FuriPubSub* input_events_pubsub; FuriPubSubSubscription* input_events_subscription; + FuriTimer* auto_lock_timer; FuriTimer* update_clock_timer; - FuriPubSub* status_pubsub; - - DesktopClock clock; - - bool in_transition : 1; - bool locked : 1; - + AnimationManager* animation_manager; FuriSemaphore* animation_semaphore; - Keybinds keybinds; + DesktopClock clock; + DesktopSettings settings; + + bool in_transition; + bool app_running; + bool locked; FuriPubSub* ascii_events_pubsub; FuriPubSubSubscription* ascii_events_subscription; }; -Desktop* desktop_alloc(void); - -void desktop_free(Desktop* desktop); void desktop_lock(Desktop* desktop, bool pin_lock); void desktop_unlock(Desktop* desktop); void desktop_set_stealth_mode_state(Desktop* desktop, bool enabled); diff --git a/applications/services/desktop/desktop_keybinds.c b/applications/services/desktop/desktop_keybinds.c new file mode 100644 index 000000000..bbb1f4c13 --- /dev/null +++ b/applications/services/desktop/desktop_keybinds.c @@ -0,0 +1,222 @@ +#include "desktop_keybinds.h" +#include "desktop_keybinds_filename.h" +#include "desktop_i.h" + +#include +#include +#include +#include +#include + +#define TAG "DesktopKeybinds" + +#define OLD_DESKTOP_KEYBINDS_VER (1) +#define OLD_DESKTOP_KEYBINDS_MAGIC (0x14) +#define OLD_DESKTOP_KEYBINDS_PATH DESKTOP_KEYBINDS_PATH_MIGRATE +#define OLD_MAX_KEYBIND_LENGTH (64) + +typedef struct { + char data[OLD_MAX_KEYBIND_LENGTH]; +} OldKeybind; + +typedef OldKeybind OldKeybinds[DesktopKeybindTypeMAX][DesktopKeybindKeyMAX]; + +void desktop_keybinds_migrate(Desktop* desktop) { + if(!storage_common_exists(desktop->storage, DESKTOP_KEYBINDS_PATH)) { + OldKeybinds old; + const bool success = saved_struct_load( + OLD_DESKTOP_KEYBINDS_PATH, + &old, + sizeof(old), + OLD_DESKTOP_KEYBINDS_MAGIC, + OLD_DESKTOP_KEYBINDS_VER); + + if(success) { + DesktopKeybinds new; + for(DesktopKeybindType type = 0; type < DesktopKeybindTypeMAX; type++) { + for(DesktopKeybindKey key = 0; key < DesktopKeybindKeyMAX; key++) { + FuriString* keybind = furi_string_alloc_set(old[type][key].data); + if(furi_string_equal(keybind, EXT_PATH("apps/Misc/nightstand.fap"))) { + furi_string_set(keybind, "Clock"); + } else if(furi_string_equal(keybind, "RFID")) { + furi_string_set(keybind, "125 kHz RFID"); + } else if(furi_string_equal(keybind, "SubGHz")) { + furi_string_set(keybind, "Sub-GHz"); + } else if(furi_string_equal(keybind, "Xtreme")) { + furi_string_set(keybind, "Momentum"); + } + new[type][key] = keybind; + } + } + desktop_keybinds_save(desktop, &new); + desktop_keybinds_free(&new); + } + } + + storage_common_remove(desktop->storage, OLD_DESKTOP_KEYBINDS_PATH); +} + +const char* desktop_keybinds_defaults[DesktopKeybindTypeMAX][DesktopKeybindKeyMAX] = { + [DesktopKeybindTypePress] = + { + [DesktopKeybindKeyUp] = "Lock Menu", + [DesktopKeybindKeyDown] = "Archive", + [DesktopKeybindKeyRight] = "Passport", + [DesktopKeybindKeyLeft] = "Clock", + }, + [DesktopKeybindTypeHold] = + { + [DesktopKeybindKeyUp] = "", + [DesktopKeybindKeyDown] = "", + [DesktopKeybindKeyRight] = "Device Info", + [DesktopKeybindKeyLeft] = "Lock with PIN", + }, +}; + +const char* desktop_keybind_types[DesktopKeybindTypeMAX] = { + [DesktopKeybindTypePress] = "Press", + [DesktopKeybindTypeHold] = "Hold", +}; + +const char* desktop_keybind_keys[DesktopKeybindKeyMAX] = { + [DesktopKeybindKeyUp] = "Up", + [DesktopKeybindKeyDown] = "Down", + [DesktopKeybindKeyRight] = "Right", + [DesktopKeybindKeyLeft] = "Left", +}; + +static FuriString* + desktop_keybinds_load_one(Desktop* desktop, DesktopKeybindType type, DesktopKeybindKey key) { + bool success = false; + FuriString* keybind = furi_string_alloc(); + FlipperFormat* file = flipper_format_file_alloc(desktop->storage); + + if(flipper_format_file_open_existing(file, DESKTOP_KEYBINDS_PATH)) { + FuriString* keybind_name = furi_string_alloc_printf( + "%s%s", desktop_keybind_types[type], desktop_keybind_keys[key]); + success = flipper_format_read_string(file, furi_string_get_cstr(keybind_name), keybind); + furi_string_free(keybind_name); + } + + flipper_format_free(file); + if(!success) { + FURI_LOG_W(TAG, "Failed to load file, using defaults"); + furi_string_set(keybind, desktop_keybinds_defaults[type][key]); + } + return keybind; +} + +void desktop_keybinds_load(Desktop* desktop, DesktopKeybinds* keybinds) { + for(DesktopKeybindType type = 0; type < DesktopKeybindTypeMAX; type++) { + for(DesktopKeybindKey key = 0; key < DesktopKeybindKeyMAX; key++) { + (*keybinds)[type][key] = furi_string_alloc_set(desktop_keybinds_defaults[type][key]); + } + } + + FlipperFormat* file = flipper_format_file_alloc(desktop->storage); + FuriString* keybind_name = furi_string_alloc(); + + if(flipper_format_file_open_existing(file, DESKTOP_KEYBINDS_PATH)) { + for(DesktopKeybindType type = 0; type < DesktopKeybindTypeMAX; type++) { + for(DesktopKeybindKey key = 0; key < DesktopKeybindKeyMAX; key++) { + furi_string_printf( + keybind_name, "%s%s", desktop_keybind_types[type], desktop_keybind_keys[key]); + if(!flipper_format_read_string( + file, furi_string_get_cstr(keybind_name), (*keybinds)[type][key])) { + furi_string_set((*keybinds)[type][key], desktop_keybinds_defaults[type][key]); + goto fail; + } + } + } + } else { + fail: + FURI_LOG_W(TAG, "Failed to load file, using defaults"); + } + + furi_string_free(keybind_name); + flipper_format_free(file); +} + +void desktop_keybinds_save(Desktop* desktop, const DesktopKeybinds* keybinds) { + FlipperFormat* file = flipper_format_file_alloc(desktop->storage); + FuriString* keybind_name = furi_string_alloc(); + + if(flipper_format_file_open_always(file, DESKTOP_KEYBINDS_PATH)) { + for(DesktopKeybindType type = 0; type < DesktopKeybindTypeMAX; type++) { + for(DesktopKeybindKey key = 0; key < DesktopKeybindKeyMAX; key++) { + furi_string_printf( + keybind_name, "%s%s", desktop_keybind_types[type], desktop_keybind_keys[key]); + if(!flipper_format_write_string_cstr( + file, + furi_string_get_cstr(keybind_name), + furi_string_get_cstr((*keybinds)[type][key]))) { + goto fail; + } + } + } + } else { + fail: + FURI_LOG_E(TAG, "Failed to save file"); + } + + furi_string_free(keybind_name); + flipper_format_free(file); +} + +void desktop_keybinds_free(DesktopKeybinds* keybinds) { + for(DesktopKeybindType type = 0; type < DesktopKeybindTypeMAX; type++) { + for(DesktopKeybindKey key = 0; key < DesktopKeybindKeyMAX; key++) { + furi_string_free((*keybinds)[type][key]); + } + } +} + +static const DesktopKeybindType keybind_types[] = { + [InputTypeShort] = DesktopKeybindTypePress, + [InputTypeLong] = DesktopKeybindTypeHold, +}; + +static const DesktopKeybindKey keybind_keys[] = { + [InputKeyUp] = DesktopKeybindKeyUp, + [InputKeyDown] = DesktopKeybindKeyDown, + [InputKeyRight] = DesktopKeybindKeyRight, + [InputKeyLeft] = DesktopKeybindKeyLeft, +}; + +void desktop_run_keybind(Desktop* desktop, InputType _type, InputKey _key) { + if(_type != InputTypeShort && _type != InputTypeLong) return; + if(_key != InputKeyUp && _key != InputKeyDown && _key != InputKeyRight && _key != InputKeyLeft) + return; + + DesktopKeybindType type = keybind_types[_type]; + DesktopKeybindKey key = keybind_keys[_key]; + FuriString* keybind = desktop_keybinds_load_one(desktop, type, key); + + if(furi_string_equal(keybind, "Apps Menu")) { + loader_start_detached_with_gui_error(desktop->loader, LOADER_APPLICATIONS_NAME, NULL); + } else if(furi_string_equal(keybind, "Archive")) { + view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopMainEventOpenArchive); + } else if(furi_string_equal(keybind, "Clock")) { + loader_start_detached_with_gui_error( + desktop->loader, EXT_PATH("apps/Tools/nightstand.fap"), ""); + } else if(furi_string_equal(keybind, "Device Info")) { + loader_start_detached_with_gui_error(desktop->loader, "Power", "about_battery"); + } else if(furi_string_equal(keybind, "Lock Menu")) { + view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopMainEventOpenLockMenu); + } else if(furi_string_equal(keybind, "Lock Keypad")) { + view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopMainEventLockKeypad); + } else if(furi_string_equal(keybind, "Lock with PIN")) { + view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopMainEventLockWithPin); + } else if(furi_string_equal(keybind, "Wipe Device")) { + loader_start_detached_with_gui_error(desktop->loader, "Storage", "wipe"); + } else { + if(storage_common_exists(desktop->storage, furi_string_get_cstr(keybind))) { + run_with_default_app(furi_string_get_cstr(keybind)); + } else { + loader_start_detached_with_gui_error( + desktop->loader, furi_string_get_cstr(keybind), NULL); + } + } + + furi_string_free(keybind); +} diff --git a/applications/services/desktop/desktop_keybinds.h b/applications/services/desktop/desktop_keybinds.h new file mode 100644 index 000000000..dfc54f054 --- /dev/null +++ b/applications/services/desktop/desktop_keybinds.h @@ -0,0 +1,27 @@ +#pragma once + +#include + +#include "desktop.h" + +typedef enum { + DesktopKeybindTypePress, + DesktopKeybindTypeHold, + DesktopKeybindTypeMAX, +} DesktopKeybindType; + +typedef enum { + DesktopKeybindKeyUp, + DesktopKeybindKeyDown, + DesktopKeybindKeyRight, + DesktopKeybindKeyLeft, + DesktopKeybindKeyMAX, +} DesktopKeybindKey; + +typedef FuriString* DesktopKeybinds[DesktopKeybindTypeMAX][DesktopKeybindKeyMAX]; + +void desktop_keybinds_migrate(Desktop* desktop); +void desktop_keybinds_load(Desktop* desktop, DesktopKeybinds* keybinds); +void desktop_keybinds_save(Desktop* desktop, const DesktopKeybinds* keybinds); +void desktop_keybinds_free(DesktopKeybinds* keybinds); +void desktop_run_keybind(Desktop* desktop, InputType _type, InputKey _key); diff --git a/applications/services/desktop/desktop_keybinds_filename.h b/applications/services/desktop/desktop_keybinds_filename.h new file mode 100644 index 000000000..71c2056eb --- /dev/null +++ b/applications/services/desktop/desktop_keybinds_filename.h @@ -0,0 +1,6 @@ +#pragma once + +#define DESKTOP_KEYBINDS_PATH INT_PATH(".desktop_keybinds.txt") + +// Moved from .config by migrate, then converted to Flipper Format by Desktop +#define DESKTOP_KEYBINDS_PATH_MIGRATE INT_PATH(".desktop.keybinds") diff --git a/applications/services/desktop/desktop_settings.c b/applications/services/desktop/desktop_settings.c index c3c80b34d..433a2b062 100644 --- a/applications/services/desktop/desktop_settings.c +++ b/applications/services/desktop/desktop_settings.c @@ -1,50 +1,42 @@ #include "desktop_settings.h" +#include "desktop_settings_filename.h" -bool DESKTOP_SETTINGS_SAVE(DesktopSettings* x) { - return saved_struct_save( +#include +#include + +#define TAG "DesktopSettings" + +#define DESKTOP_SETTINGS_VER (11) +#define DESKTOP_SETTINGS_MAGIC (0x13) // Different from OFW 0x17 + +void desktop_settings_load(DesktopSettings* settings) { + furi_assert(settings); + + const bool success = saved_struct_load( DESKTOP_SETTINGS_PATH, - x, + settings, sizeof(DesktopSettings), DESKTOP_SETTINGS_MAGIC, DESKTOP_SETTINGS_VER); -} -bool DESKTOP_SETTINGS_LOAD(DesktopSettings* x) { - return saved_struct_load( - DESKTOP_SETTINGS_PATH, - x, - sizeof(DesktopSettings), - DESKTOP_SETTINGS_MAGIC, - DESKTOP_SETTINGS_VER); -} - -bool DESKTOP_KEYBINDS_SAVE(Keybinds* x, size_t size) { - return saved_struct_save( - DESKTOP_KEYBINDS_PATH, x, size, DESKTOP_KEYBINDS_MAGIC, DESKTOP_KEYBINDS_VER); -} - -bool DESKTOP_KEYBINDS_LOAD(Keybinds* x, size_t size) { - bool ok = saved_struct_load( - DESKTOP_KEYBINDS_PATH, x, size, DESKTOP_KEYBINDS_MAGIC, DESKTOP_KEYBINDS_VER); - if(ok) { - for(KeybindType i = 0; i < KeybindTypeCount; i++) { - for(KeybindKey j = 0; j < KeybindKeyCount; j++) { - char* keybind = (*x)[i][j].data; - if(!strncmp(keybind, EXT_PATH("apps/Misc/nightstand.fap"), MAX_KEYBIND_LENGTH)) { - strcpy(keybind, "Clock"); - } - } - } - } else { - memset(x, 0, size); - strcpy((*x)[KeybindTypePress][KeybindKeyUp].data, "Lock Menu"); - strcpy((*x)[KeybindTypePress][KeybindKeyDown].data, "Archive"); - strcpy((*x)[KeybindTypePress][KeybindKeyRight].data, "Passport"); - strcpy((*x)[KeybindTypePress][KeybindKeyLeft].data, "Clock"); - strcpy((*x)[KeybindTypeHold][KeybindKeyUp].data, ""); - strcpy((*x)[KeybindTypeHold][KeybindKeyDown].data, ""); - strcpy((*x)[KeybindTypeHold][KeybindKeyRight].data, "Device Info"); - strcpy((*x)[KeybindTypeHold][KeybindKeyLeft].data, "Lock with PIN"); + if(!success) { + FURI_LOG_W(TAG, "Failed to load file, using defaults"); + memset(settings, 0, sizeof(DesktopSettings)); + // desktop_settings_save(settings); + } +} + +void desktop_settings_save(const DesktopSettings* settings) { + furi_assert(settings); + + const bool success = saved_struct_save( + DESKTOP_SETTINGS_PATH, + settings, + sizeof(DesktopSettings), + DESKTOP_SETTINGS_MAGIC, + DESKTOP_SETTINGS_VER); + + if(!success) { + FURI_LOG_E(TAG, "Failed to save file"); } - return ok; } diff --git a/applications/services/desktop/desktop_settings.h b/applications/services/desktop/desktop_settings.h index 420801ba6..9ef6ede28 100644 --- a/applications/services/desktop/desktop_settings.h +++ b/applications/services/desktop/desktop_settings.h @@ -1,70 +1,12 @@ #pragma once -#include #include -#include -#include -#include - -#define DESKTOP_SETTINGS_VER (11) - -#define DESKTOP_SETTINGS_PATH INT_PATH(".desktop.settings") -#define DESKTOP_SETTINGS_MAGIC (0x17) - -#define DESKTOP_KEYBINDS_VER (1) - -#define DESKTOP_KEYBINDS_PATH CFG_PATH("desktop.keybinds") -#define DESKTOP_KEYBINDS_MAGIC (0x14) - -#define DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG "run_pin_setup" - -#define MAX_PIN_SIZE 10 -#define MIN_PIN_SIZE 4 -#define MAX_KEYBIND_LENGTH 64 typedef struct { - InputKey data[MAX_PIN_SIZE]; - uint8_t length; -} PinCode; - -typedef struct { - char data[MAX_KEYBIND_LENGTH]; -} Keybind; - -typedef enum { - KeybindTypePress, - KeybindTypeHold, - KeybindTypeCount, -} KeybindType; - -typedef enum { - KeybindKeyUp, - KeybindKeyDown, - KeybindKeyRight, - KeybindKeyLeft, - KeybindKeyCount, -} KeybindKey; - -typedef struct { - PinCode pin_code; uint32_t auto_lock_delay_ms; - bool auto_lock_with_pin; + uint8_t auto_lock_with_pin; + uint8_t display_clock; } DesktopSettings; -typedef Keybind Keybinds[KeybindTypeCount][KeybindKeyCount]; - -#ifdef __cplusplus -extern "C" { -#endif - -bool DESKTOP_SETTINGS_SAVE(DesktopSettings* x); - -bool DESKTOP_SETTINGS_LOAD(DesktopSettings* x); - -bool DESKTOP_KEYBINDS_SAVE(Keybinds* x, size_t size); - -bool DESKTOP_KEYBINDS_LOAD(Keybinds* x, size_t size); - -#ifdef __cplusplus -} -#endif +void desktop_settings_load(DesktopSettings* settings); +void desktop_settings_save(const DesktopSettings* settings); diff --git a/applications/services/desktop/desktop_settings_filename.h b/applications/services/desktop/desktop_settings_filename.h new file mode 100644 index 000000000..7930dd90f --- /dev/null +++ b/applications/services/desktop/desktop_settings_filename.h @@ -0,0 +1,5 @@ +#pragma once + +#define DESKTOP_SETTINGS_FILE_NAME ".desktop.settings" + +#define DESKTOP_SETTINGS_PATH INT_PATH(DESKTOP_SETTINGS_FILE_NAME) diff --git a/applications/services/desktop/helpers/pin.c b/applications/services/desktop/helpers/pin.c deleted file mode 100644 index f8ca13ae9..000000000 --- a/applications/services/desktop/helpers/pin.c +++ /dev/null @@ -1,67 +0,0 @@ -#include "pin.h" - -#include -#include -#include -#include -#include -#include - -static const NotificationSequence sequence_pin_fail = { - &message_display_backlight_on, - - &message_red_255, - &message_vibro_on, - &message_delay_100, - &message_vibro_off, - &message_red_0, - - &message_delay_250, - - &message_red_255, - &message_vibro_on, - &message_delay_100, - &message_vibro_off, - &message_red_0, - NULL, -}; - -void desktop_pin_lock_error_notify(void) { - NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); - notification_message(notification, &sequence_pin_fail); - furi_record_close(RECORD_NOTIFICATION); -} - -uint32_t desktop_pin_lock_get_fail_timeout(void) { - uint32_t pin_fails = furi_hal_rtc_get_pin_fails(); - if(pin_fails < 3) { - return 0; - } - // Use for loop to avoid including pow() function (4kb of dfu flash) - uint32_t mult = 1; - for(size_t i = 0; i < pin_fails - 3; i++) { - mult *= 2; - } - return 30 * mult; -} - -bool desktop_pin_compare(const PinCode* pin_code1, const PinCode* pin_code2) { - furi_assert(pin_code1); - furi_assert(pin_code2); - bool result = false; - - if(pin_code1->length == pin_code2->length) { - result = !memcmp(pin_code1->data, pin_code2->data, pin_code1->length); - } - - return result; -} - -bool desktop_pin_is_valid(const PinCode* pin_code) { - bool ok = pin_code->length >= MIN_PIN_SIZE && pin_code->length <= MAX_PIN_SIZE; - for(size_t i = 0; ok && i < pin_code->length; i++) { - ok = ok && (pin_code->data[i] == InputKeyUp || pin_code->data[i] == InputKeyDown || - pin_code->data[i] == InputKeyRight || pin_code->data[i] == InputKeyLeft); - } - return ok; -} diff --git a/applications/services/desktop/helpers/pin.h b/applications/services/desktop/helpers/pin.h deleted file mode 100644 index a3f65868d..000000000 --- a/applications/services/desktop/helpers/pin.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include -#include -#include "../desktop.h" -#include - -void desktop_pin_lock_error_notify(void); - -uint32_t desktop_pin_lock_get_fail_timeout(void); - -bool desktop_pin_compare(const PinCode* pin_code1, const PinCode* pin_code2); - -bool desktop_pin_is_valid(const PinCode* pin_code); diff --git a/applications/services/desktop/helpers/pin_code.c b/applications/services/desktop/helpers/pin_code.c new file mode 100644 index 000000000..6553272e0 --- /dev/null +++ b/applications/services/desktop/helpers/pin_code.c @@ -0,0 +1,90 @@ +#include "pin_code.h" + +#include + +#include +#include + +#define DESKTOP_PIN_CODE_DIGIT_BIT_WIDTH (2) +#define DESKTOP_PIN_CODE_LENGTH_OFFSET (28) + +static const NotificationSequence sequence_pin_fail = { + &message_display_backlight_on, + + &message_red_255, + &message_vibro_on, + &message_delay_100, + &message_vibro_off, + &message_red_0, + + &message_delay_250, + + &message_red_255, + &message_vibro_on, + &message_delay_100, + &message_vibro_off, + &message_red_0, + NULL, +}; + +static uint32_t desktop_pin_code_pack(const DesktopPinCode* pin_code) { + furi_check(pin_code); + furi_check(pin_code->length <= sizeof(pin_code->data)); + + uint32_t reg_value = 0; + + for(uint8_t i = 0; i < pin_code->length; ++i) { + furi_check(pin_code->data[i] < (1 << DESKTOP_PIN_CODE_DIGIT_BIT_WIDTH)); + reg_value |= (uint32_t)pin_code->data[i] << (i * DESKTOP_PIN_CODE_DIGIT_BIT_WIDTH); + } + + reg_value |= (uint32_t)pin_code->length << DESKTOP_PIN_CODE_LENGTH_OFFSET; + + return reg_value; +} + +bool desktop_pin_code_is_set(void) { + return furi_hal_rtc_get_pin_value() >> DESKTOP_PIN_CODE_LENGTH_OFFSET; +} + +void desktop_pin_code_set(const DesktopPinCode* pin_code) { + furi_hal_rtc_set_pin_value(desktop_pin_code_pack(pin_code)); +} + +void desktop_pin_code_reset(void) { + furi_hal_rtc_set_pin_value(0); +} + +bool desktop_pin_code_check(const DesktopPinCode* pin_code) { + return furi_hal_rtc_get_pin_value() == desktop_pin_code_pack(pin_code); +} + +bool desktop_pin_code_is_equal(const DesktopPinCode* pin_code1, const DesktopPinCode* pin_code2) { + furi_check(pin_code1); + furi_check(pin_code1->length <= sizeof(pin_code1->data)); + furi_check(pin_code2); + furi_check(pin_code2->length <= sizeof(pin_code2->data)); + + return pin_code1->length == pin_code2->length && + memcmp(pin_code1->data, pin_code2->data, pin_code1->length) == 0; +} + +void desktop_pin_lock_error_notify(void) { + NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); + notification_message(notification, &sequence_pin_fail); + furi_record_close(RECORD_NOTIFICATION); +} + +uint32_t desktop_pin_lock_get_fail_timeout(void) { + uint32_t pin_fails = furi_hal_rtc_get_pin_fails(); + if(pin_fails < 3) { + return 0; + } + + // Use for loop to avoid including pow() function (4kb of dfu flash) + uint32_t mult = 1; + for(size_t i = 0; i < pin_fails - 3; i++) { + mult *= 2; + } + return 30 * mult; +} diff --git a/applications/services/desktop/helpers/pin_code.h b/applications/services/desktop/helpers/pin_code.h new file mode 100644 index 000000000..4b6615105 --- /dev/null +++ b/applications/services/desktop/helpers/pin_code.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +#define DESKTOP_PIN_CODE_MAX_LEN (10) + +#define DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG "run_pin_setup" + +typedef struct { + uint8_t data[DESKTOP_PIN_CODE_MAX_LEN]; + uint8_t length; +} DesktopPinCode; + +bool desktop_pin_code_is_set(void); + +void desktop_pin_code_set(const DesktopPinCode* pin_code); + +void desktop_pin_code_reset(void); + +bool desktop_pin_code_check(const DesktopPinCode* pin_code); + +bool desktop_pin_code_is_equal(const DesktopPinCode* pin_code1, const DesktopPinCode* pin_code2); + +void desktop_pin_lock_error_notify(void); + +uint32_t desktop_pin_lock_get_fail_timeout(void); diff --git a/applications/services/desktop/helpers/slideshow_filename.h b/applications/services/desktop/helpers/slideshow_filename.h new file mode 100644 index 000000000..2250d91dd --- /dev/null +++ b/applications/services/desktop/helpers/slideshow_filename.h @@ -0,0 +1,3 @@ +#pragma once + +#define SLIDESHOW_FILE_NAME ".slideshow" diff --git a/applications/services/desktop/scenes/desktop_scene_i.h b/applications/services/desktop/scenes/desktop_scene_i.h deleted file mode 100644 index f481733ac..000000000 --- a/applications/services/desktop/scenes/desktop_scene_i.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -#define SCENE_LOCKED_FIRST_ENTER 0 -#define SCENE_LOCKED_REPEAT_ENTER 1 diff --git a/applications/services/desktop/scenes/desktop_scene_lock_menu.c b/applications/services/desktop/scenes/desktop_scene_lock_menu.c index f0b02105a..d3987b6ee 100644 --- a/applications/services/desktop/scenes/desktop_scene_lock_menu.c +++ b/applications/services/desktop/scenes/desktop_scene_lock_menu.c @@ -10,10 +10,17 @@ #include #include "../views/desktop_view_lock_menu.h" #include "desktop_scene.h" -#include "../helpers/pin.h" +#include "../helpers/pin_code.h" #include + #define TAG "DesktopSceneLock" +typedef enum { + CheckPinNo, + CheckPinLock, + CheckPinLockOff, +} CheckPin; + void desktop_scene_lock_menu_callback(DesktopEvent event, void* context) { Desktop* desktop = (Desktop*)context; view_dispatcher_send_custom_event(desktop->view_dispatcher, event); @@ -22,17 +29,14 @@ void desktop_scene_lock_menu_callback(DesktopEvent event, void* context) { void desktop_scene_lock_menu_on_enter(void* context) { Desktop* desktop = (Desktop*)context; - scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0); + scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, CheckPinNo); desktop_lock_menu_set_callback(desktop->lock_menu, desktop_scene_lock_menu_callback, desktop); - desktop_lock_menu_set_pin_state( - desktop->lock_menu, desktop_pin_is_valid(&desktop->settings.pin_code)); + desktop_lock_menu_set_pin_state(desktop->lock_menu, desktop_pin_code_is_set()); desktop_lock_menu_set_stealth_mode_state( desktop->lock_menu, furi_hal_rtc_is_flag_set(FuriHalRtcFlagStealthMode)); desktop_lock_menu_set_idx(desktop->lock_menu, 3); - Gui* gui = furi_record_open(RECORD_GUI); - gui_set_hide_statusbar(gui, true); - furi_record_close(RECORD_GUI); + gui_set_hide_statusbar(desktop->gui, true); view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdLockMenu); } @@ -57,19 +61,18 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) { bool consumed = false; if(event.type == SceneManagerEventTypeTick) { - int check_pin_changed = + CheckPin check_pin_changed = scene_manager_get_scene_state(desktop->scene_manager, DesktopSceneLockMenu); - if(check_pin_changed) { - if(desktop_pin_is_valid(&desktop->settings.pin_code)) { - desktop_lock_menu_set_pin_state(desktop->lock_menu, true); - scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0); - desktop_lock(desktop, true); - if(check_pin_changed == 2) { - Power* power = furi_record_open(RECORD_POWER); - furi_delay_ms(500); - power_off(power); - furi_record_close(RECORD_POWER); - } + if(check_pin_changed != CheckPinNo && desktop_pin_code_is_set()) { + desktop_lock_menu_set_pin_state(desktop->lock_menu, true); + scene_manager_set_scene_state( + desktop->scene_manager, DesktopSceneLockMenu, CheckPinNo); + desktop_lock(desktop, true); + if(check_pin_changed == CheckPinLockOff) { + Power* power = furi_record_open(RECORD_POWER); + furi_delay_ms(500); + power_off(power); + furi_record_close(RECORD_POWER); } } } else if(event.type == SceneManagerEventTypeCustom) { @@ -87,18 +90,19 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) { break; case DesktopLockMenuEventLockPinCode: desktop_scene_lock_menu_save_settings(desktop); - if(desktop_pin_is_valid(&desktop->settings.pin_code)) { + if(desktop_pin_code_is_set()) { desktop_lock(desktop, true); } else { loader_start_detached_with_gui_error( desktop->loader, "Desktop", DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG); - scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 1); + scene_manager_set_scene_state( + desktop->scene_manager, DesktopSceneLockMenu, CheckPinLock); } consumed = true; break; case DesktopLockMenuEventLockPinOff: desktop_scene_lock_menu_save_settings(desktop); - if(desktop_pin_is_valid(&desktop->settings.pin_code)) { + if(desktop_pin_code_is_set()) { desktop_lock(desktop, true); Power* power = furi_record_open(RECORD_POWER); furi_delay_ms(500); @@ -107,7 +111,8 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) { } else { loader_start_detached_with_gui_error( desktop->loader, "Desktop", DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG); - scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 2); + scene_manager_set_scene_state( + desktop->scene_manager, DesktopSceneLockMenu, CheckPinLockOff); } consumed = true; break; @@ -126,7 +131,7 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) { break; } } else if(event.type == SceneManagerEventTypeBack) { - scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0); + scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, CheckPinNo); } return consumed; } @@ -135,7 +140,5 @@ void desktop_scene_lock_menu_on_exit(void* context) { Desktop* desktop = (Desktop*)context; desktop_scene_lock_menu_save_settings(desktop); - Gui* gui = furi_record_open(RECORD_GUI); - gui_set_hide_statusbar(gui, false); - furi_record_close(RECORD_GUI); + gui_set_hide_statusbar(desktop->gui, false); } diff --git a/applications/services/desktop/scenes/desktop_scene_locked.c b/applications/services/desktop/scenes/desktop_scene_locked.c index e5bda0e97..a9fc3b7db 100644 --- a/applications/services/desktop/scenes/desktop_scene_locked.c +++ b/applications/services/desktop/scenes/desktop_scene_locked.c @@ -6,15 +6,14 @@ #include "../desktop.h" #include "../desktop_i.h" -#include "../helpers/pin.h" +#include "../helpers/pin_code.h" #include "../animations/animation_manager.h" #include "../views/desktop_events.h" #include "../views/desktop_view_locked.h" #include "desktop_scene.h" -#include "desktop_scene_i.h" -#include +#include "desktop_scene_locked.h" -#define TAG "DesktopSrv" +#include #define WRONG_PIN_HEADER_TIMEOUT 3000 #define INPUT_PIN_VIEW_TIMEOUT 15000 @@ -45,14 +44,13 @@ void desktop_scene_locked_on_enter(void* context) { bool switch_to_timeout_scene = false; uint32_t state = scene_manager_get_scene_state(desktop->scene_manager, DesktopSceneLocked); - if(state == SCENE_LOCKED_FIRST_ENTER) { - bool pin_locked = furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock); + if(state == DesktopSceneLockedStateFirstEnter) { view_port_enabled_set(desktop->lock_icon_viewport, true); Gui* gui = furi_record_open(RECORD_GUI); gui_set_lockdown(gui, true); furi_record_close(RECORD_GUI); - if(pin_locked) { + if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock)) { desktop_view_locked_lock(desktop->locked_view, true); uint32_t pin_timeout = desktop_pin_lock_get_fail_timeout(); if(pin_timeout > 0) { @@ -67,7 +65,7 @@ void desktop_scene_locked_on_enter(void* context) { desktop_view_locked_close_cover(desktop->locked_view); } scene_manager_set_scene_state( - desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_REPEAT_ENTER); + desktop->scene_manager, DesktopSceneLocked, DesktopSceneLockedStateRepeatEnter); } if(switch_to_timeout_scene) { diff --git a/applications/services/desktop/scenes/desktop_scene_locked.h b/applications/services/desktop/scenes/desktop_scene_locked.h new file mode 100644 index 000000000..7d5b6b7bc --- /dev/null +++ b/applications/services/desktop/scenes/desktop_scene_locked.h @@ -0,0 +1,6 @@ +#pragma once + +typedef enum { + DesktopSceneLockedStateFirstEnter, + DesktopSceneLockedStateRepeatEnter, +} DesktopSceneLockedState; diff --git a/applications/services/desktop/scenes/desktop_scene_pin_input.c b/applications/services/desktop/scenes/desktop_scene_pin_input.c index 8c93bc2aa..a7a05667f 100644 --- a/applications/services/desktop/scenes/desktop_scene_pin_input.c +++ b/applications/services/desktop/scenes/desktop_scene_pin_input.c @@ -11,7 +11,7 @@ #include "../desktop_i.h" #include "../views/desktop_events.h" #include "../views/desktop_view_pin_input.h" -#include "../helpers/pin.h" +#include "../helpers/pin_code.h" #include "desktop_scene.h" #define WRONG_PIN_HEADER_TIMEOUT 3000 @@ -50,18 +50,21 @@ static void desktop_scene_pin_input_back_callback(void* context) { view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopPinInputEventBack); } -static void desktop_scene_pin_input_done_callback(const PinCode* pin_code, void* context) { +static void desktop_scene_pin_input_done_callback(const DesktopPinCode* pin_code, void* context) { Desktop* desktop = (Desktop*)context; - if(desktop_pin_compare(&desktop->settings.pin_code, pin_code)) { + + if(desktop_pin_code_check(pin_code)) { view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopPinInputEventUnlocked); + } else { uint32_t pin_fails = furi_hal_rtc_get_pin_fails() + 1; if(pin_fails >= 10 && momentum_settings.bad_pins_format) { - furi_hal_rtc_reset_registers(); - furi_hal_rtc_set_flag(FuriHalRtcFlagStorageFormatInternal); - storage_sd_format(furi_record_open(RECORD_STORAGE)); + Storage* storage = furi_record_open(RECORD_STORAGE); + storage_sd_format(storage); furi_record_close(RECORD_STORAGE); - power_reboot(PowerBootModeNormal); + furi_hal_rtc_reset_registers(); + Power* power = furi_record_open(RECORD_POWER); + power_reboot(power, PowerBootModeNormal); } furi_hal_rtc_set_pin_fails(pin_fails); view_dispatcher_send_custom_event( diff --git a/applications/services/desktop/scenes/desktop_scene_slideshow.c b/applications/services/desktop/scenes/desktop_scene_slideshow.c index 270302340..a5e699b5b 100644 --- a/applications/services/desktop/scenes/desktop_scene_slideshow.c +++ b/applications/services/desktop/scenes/desktop_scene_slideshow.c @@ -46,10 +46,7 @@ bool desktop_scene_slideshow_on_event(void* context, SceneManagerEvent event) { } void desktop_scene_slideshow_on_exit(void* context) { - Desktop* desktop = (Desktop*)context; - + Desktop* desktop = context; gui_set_hide_statusbar(desktop->gui, false); - Storage* storage = furi_record_open(RECORD_STORAGE); - storage_common_remove(storage, SLIDESHOW_FS_PATH); - furi_record_close(RECORD_STORAGE); + storage_common_remove(desktop->storage, SLIDESHOW_FS_PATH); } diff --git a/applications/services/desktop/views/desktop_events.h b/applications/services/desktop/views/desktop_events.h index 47114d72a..3f2896912 100644 --- a/applications/services/desktop/views/desktop_events.h +++ b/applications/services/desktop/views/desktop_events.h @@ -56,6 +56,8 @@ typedef enum { DesktopGlobalAfterAppFinished, DesktopGlobalAutoLock, DesktopGlobalApiUnlock, + DesktopGlobalSaveSettings, + DesktopGlobalReloadSettings, DesktopMainEventLockKeypad, DesktopLockedEventOpenPowerOff, diff --git a/applications/services/desktop/views/desktop_view_lock_menu.c b/applications/services/desktop/views/desktop_view_lock_menu.c index d3eba7d32..b001df687 100644 --- a/applications/services/desktop/views/desktop_view_lock_menu.c +++ b/applications/services/desktop/views/desktop_view_lock_menu.c @@ -43,7 +43,7 @@ void desktop_lock_menu_set_pin_state(DesktopLockMenuView* lock_menu, bool pin_is DesktopLockMenuViewModel * model, { model->pin_is_set = pin_is_set; - model->pin_lock = pin_is_set; + model->lock_popup_index = pin_is_set; // Select with PIN by default if set }, true); } @@ -166,13 +166,13 @@ void desktop_lock_menu_draw_callback(Canvas* canvas, void* model) { } } - if(m->show_lock_menu) { + if(m->show_lock_popup) { canvas_set_font(canvas, FontSecondary); elements_bold_rounded_frame(canvas, 24, 4, 80, 56); canvas_draw_str_aligned(canvas, 64, 16, AlignCenter, AlignCenter, "Keypad Lock"); canvas_draw_str_aligned(canvas, 64, 32, AlignCenter, AlignCenter, "PIN Code Lock"); canvas_draw_str_aligned(canvas, 64, 48, AlignCenter, AlignCenter, "PIN Lock + OFF"); - elements_frame(canvas, 28, 8 + m->pin_lock * 16, 72, 15); + elements_frame(canvas, 28, 8 + m->lock_popup_index * 16, 72, 15); } } @@ -187,8 +187,8 @@ bool desktop_lock_menu_input_callback(InputEvent* event, void* context) { DesktopLockMenuView* lock_menu = context; uint8_t idx = 0; - int pin_lock = 0; - bool show_lock_menu = false; + bool show_lock_popup = false; + DesktopLockMenuPopupIndex lock_popup_index = 0; bool stealth_mode = false; bool consumed = true; @@ -196,26 +196,28 @@ bool desktop_lock_menu_input_callback(InputEvent* event, void* context) { lock_menu->view, DesktopLockMenuViewModel * model, { - show_lock_menu = model->show_lock_menu; + show_lock_popup = model->show_lock_popup; stealth_mode = model->stealth_mode; if((event->type == InputTypeShort) || (event->type == InputTypeRepeat)) { - if(model->show_lock_menu) { + if(model->show_lock_popup) { if(event->key == InputKeyUp) { - model->pin_lock--; - if(model->pin_lock < 0) { - model->pin_lock = 2; + if(model->lock_popup_index == 0) { + model->lock_popup_index = DesktopLockMenuPopupIndexMAX - 1; + } else { + model->lock_popup_index--; } } else if(event->key == InputKeyDown) { - model->pin_lock++; - if(model->pin_lock > 2) { - model->pin_lock = 0; + if(model->lock_popup_index == DesktopLockMenuPopupIndexMAX - 1) { + model->lock_popup_index = 0; + } else { + model->lock_popup_index++; } } else if(event->key == InputKeyBack || event->key == InputKeyOk) { - model->show_lock_menu = false; + model->show_lock_popup = false; } } else { if(model->idx == DesktopLockMenuIndexLock && event->key == InputKeyOk) { - model->show_lock_menu = true; + model->show_lock_popup = true; } else if(model->idx < 6) { if(event->key == InputKeyUp || event->key == InputKeyDown) { if(model->idx % 2) { @@ -250,21 +252,21 @@ bool desktop_lock_menu_input_callback(InputEvent* event, void* context) { } } idx = model->idx; - pin_lock = model->pin_lock; + lock_popup_index = model->lock_popup_index; }, true); DesktopEvent desktop_event = 0; - if(show_lock_menu) { + if(show_lock_popup) { if(event->key == InputKeyOk && event->type == InputTypeShort) { - switch(pin_lock) { - case 0: + switch(lock_popup_index) { + case DesktopLockMenuPopupIndexKeypad: desktop_event = DesktopLockMenuEventLockKeypad; break; - case 1: + case DesktopLockMenuPopupIndexPinCode: desktop_event = DesktopLockMenuEventLockPinCode; break; - case 2: + case DesktopLockMenuPopupIndexPinOff: desktop_event = DesktopLockMenuEventLockPinOff; break; default: diff --git a/applications/services/desktop/views/desktop_view_lock_menu.h b/applications/services/desktop/views/desktop_view_lock_menu.h index 8fb0c2739..21eb26e30 100644 --- a/applications/services/desktop/views/desktop_view_lock_menu.h +++ b/applications/services/desktop/views/desktop_view_lock_menu.h @@ -23,14 +23,21 @@ struct DesktopLockMenuView { bool save_bt; }; +typedef enum { + DesktopLockMenuPopupIndexKeypad, + DesktopLockMenuPopupIndexPinCode, + DesktopLockMenuPopupIndexPinOff, + DesktopLockMenuPopupIndexMAX, +} DesktopLockMenuPopupIndex; + typedef struct { uint8_t idx; bool _dummy_mode; // Unused, kept for compatibility bool stealth_mode; bool pin_is_set; - int pin_lock; - bool show_lock_menu; + bool show_lock_popup; + DesktopLockMenuPopupIndex lock_popup_index; DesktopLockMenuView* lock_menu; } DesktopLockMenuViewModel; diff --git a/applications/services/desktop/views/desktop_view_pin_input.c b/applications/services/desktop/views/desktop_view_pin_input.c index 965b5cceb..c89a143c8 100644 --- a/applications/services/desktop/views/desktop_view_pin_input.c +++ b/applications/services/desktop/views/desktop_view_pin_input.c @@ -6,7 +6,6 @@ #include #include "desktop_view_pin_input.h" -#include #define NO_ACTIVITY_TIMEOUT 15000 @@ -14,6 +13,9 @@ #define DEFAULT_PIN_X 64 #define DEFAULT_PIN_Y 32 +#define MIN_PIN_LENGTH 4 +#define MAX_PIN_LENGTH DESKTOP_PIN_CODE_MAX_LEN + struct DesktopViewPinInput { View* view; DesktopViewPinInputCallback back_callback; @@ -24,7 +26,7 @@ struct DesktopViewPinInput { }; typedef struct { - PinCode pin; + DesktopPinCode pin; bool pin_hidden; bool locked_input; uint8_t pin_x; @@ -50,7 +52,7 @@ static bool desktop_view_pin_input_input(InputEvent* event, void* context) { bool call_back_callback = false; bool call_done_callback = false; - PinCode pin_code = {0}; + DesktopPinCode pin_code = {0}; if(event->type == InputTypeShort) { switch(event->key) { @@ -59,13 +61,13 @@ static bool desktop_view_pin_input_input(InputEvent* event, void* context) { case InputKeyDown: case InputKeyUp: if(!model->locked_input) { - if(model->pin.length < MAX_PIN_SIZE) { + if(model->pin.length < MAX_PIN_LENGTH) { model->pin.data[model->pin.length++] = event->key; } } break; case InputKeyOk: - if(model->pin.length >= MIN_PIN_SIZE) { + if(model->pin.length >= MIN_PIN_LENGTH) { call_done_callback = true; pin_code = model->pin; } @@ -102,7 +104,7 @@ static void desktop_view_pin_input_draw_cells(Canvas* canvas, DesktopViewPinInpu furi_assert(model); uint8_t draw_pin_size = MAX(4, model->pin.length + 1); - if(model->locked_input || (model->pin.length == MAX_PIN_SIZE)) { + if(model->locked_input || (model->pin.length == MAX_PIN_LENGTH)) { draw_pin_size = model->pin.length; } @@ -155,7 +157,7 @@ static void desktop_view_pin_input_draw(Canvas* canvas, void* context) { canvas_draw_str(canvas, 16, 60, "= clear"); } - if(model->button_label && ((model->pin.length >= MIN_PIN_SIZE) || model->locked_input)) { + if(model->button_label && ((model->pin.length >= MIN_PIN_LENGTH) || model->locked_input)) { elements_button_center(canvas, model->button_label); } @@ -247,7 +249,7 @@ void desktop_view_pin_input_unlock_input(DesktopViewPinInput* pin_input) { view_commit_model(pin_input->view, true); } -void desktop_view_pin_input_set_pin(DesktopViewPinInput* pin_input, const PinCode* pin) { +void desktop_view_pin_input_set_pin(DesktopViewPinInput* pin_input, const DesktopPinCode* pin) { furi_assert(pin_input); furi_assert(pin); diff --git a/applications/services/desktop/views/desktop_view_pin_input.h b/applications/services/desktop/views/desktop_view_pin_input.h index c430aff9f..4605b6ff1 100644 --- a/applications/services/desktop/views/desktop_view_pin_input.h +++ b/applications/services/desktop/views/desktop_view_pin_input.h @@ -1,16 +1,17 @@ #pragma once #include -#include + +#include "../helpers/pin_code.h" typedef void (*DesktopViewPinInputCallback)(void*); -typedef void (*DesktopViewPinInputDoneCallback)(const PinCode* pin_code, void*); +typedef void (*DesktopViewPinInputDoneCallback)(const DesktopPinCode* pin_code, void*); typedef struct DesktopViewPinInput DesktopViewPinInput; DesktopViewPinInput* desktop_view_pin_input_alloc(void); void desktop_view_pin_input_free(DesktopViewPinInput*); -void desktop_view_pin_input_set_pin(DesktopViewPinInput* pin_input, const PinCode* pin); +void desktop_view_pin_input_set_pin(DesktopViewPinInput* pin_input, const DesktopPinCode* pin_code); void desktop_view_pin_input_reset_pin(DesktopViewPinInput* pin_input); void desktop_view_pin_input_hide_pin(DesktopViewPinInput* pin_input, bool pin_hidden); void desktop_view_pin_input_set_label_button(DesktopViewPinInput* pin_input, const char* label); diff --git a/applications/services/desktop/views/desktop_view_slideshow.c b/applications/services/desktop/views/desktop_view_slideshow.c index 0fd32676a..201e7108a 100644 --- a/applications/services/desktop/views/desktop_view_slideshow.c +++ b/applications/services/desktop/views/desktop_view_slideshow.c @@ -13,6 +13,7 @@ struct DesktopSlideshowView { DesktopSlideshowViewCallback callback; void* context; FuriTimer* timer; + FuriTimer* auto_timer; }; diff --git a/applications/services/desktop/views/desktop_view_slideshow.h b/applications/services/desktop/views/desktop_view_slideshow.h index 9c026370f..942a0d25a 100644 --- a/applications/services/desktop/views/desktop_view_slideshow.h +++ b/applications/services/desktop/views/desktop_view_slideshow.h @@ -3,9 +3,10 @@ #include #include "desktop_events.h" +#include "../helpers/slideshow_filename.h" #include -#define SLIDESHOW_FS_PATH EXT_PATH(".slideshow") +#define SLIDESHOW_FS_PATH INT_PATH(SLIDESHOW_FILE_NAME) typedef struct DesktopSlideshowView DesktopSlideshowView; diff --git a/applications/services/dialogs/dialogs_module_file_browser.c b/applications/services/dialogs/dialogs_module_file_browser.c index b1558f1e9..12a7439e6 100644 --- a/applications/services/dialogs/dialogs_module_file_browser.c +++ b/applications/services/dialogs/dialogs_module_file_browser.c @@ -49,12 +49,11 @@ bool dialogs_app_process_module_file_browser(const DialogsAppMessageDataFileBrow file_browser_start(file_browser, data->preselected_filename); view_holder_set_view(view_holder, file_browser_get_view(file_browser)); - view_holder_start(view_holder); api_lock_wait_unlock(file_browser_context->lock); ret = file_browser_context->result; - view_holder_stop(view_holder); + view_holder_set_view(view_holder, NULL); view_holder_free(view_holder); file_browser_stop(file_browser); file_browser_free(file_browser); diff --git a/applications/services/dialogs/dialogs_module_message.c b/applications/services/dialogs/dialogs_module_message.c index a71f403c5..9dc9ff9cb 100644 --- a/applications/services/dialogs/dialogs_module_message.c +++ b/applications/services/dialogs/dialogs_module_message.c @@ -88,12 +88,11 @@ DialogMessageButton dialogs_app_process_module_message(const DialogsAppMessageDa dialog_ex_set_right_button_text(dialog_ex, message->right_button_text); view_holder_set_view(view_holder, dialog_ex_get_view(dialog_ex)); - view_holder_start(view_holder); api_lock_wait_unlock(message_context->lock); ret = message_context->result; - view_holder_stop(view_holder); + view_holder_set_view(view_holder, NULL); view_holder_free(view_holder); dialog_ex_free(dialog_ex); api_lock_free(message_context->lock); diff --git a/applications/services/dolphin/application.fam b/applications/services/dolphin/application.fam index 5d275a7b7..78a097e67 100644 --- a/applications/services/dolphin/application.fam +++ b/applications/services/dolphin/application.fam @@ -6,8 +6,5 @@ App( cdefines=["SRV_DOLPHIN"], stack_size=1 * 1024, order=50, - sdk_headers=[ - "dolphin.h", - "helpers/dolphin_state.h", - ], + sdk_headers=["dolphin.h"], ) diff --git a/applications/services/dolphin/dolphin.c b/applications/services/dolphin/dolphin.c index 734fa1bae..fde0509f9 100644 --- a/applications/services/dolphin/dolphin.c +++ b/applications/services/dolphin/dolphin.c @@ -1,6 +1,7 @@ #include "dolphin_i.h" #include +#include #include #define TAG "Dolphin" @@ -84,6 +85,15 @@ FuriPubSub* dolphin_get_pubsub(Dolphin* dolphin) { return dolphin->pubsub; } +void dolphin_reload_state(Dolphin* dolphin) { + furi_check(dolphin); + + DolphinEvent event; + event.type = DolphinEventTypeReloadState; + + dolphin_event_send_wait(dolphin, &event); +} + // Private functions static void dolphin_butthurt_timer_callback(void* context) { @@ -192,8 +202,17 @@ static void dolphin_update_clear_limits_timer_period(void* context) { FURI_LOG_D(TAG, "Daily limits reset in %lu ms", time_to_clear_limits); } -static bool dolphin_process_event(FuriMessageQueue* queue, void* context) { - UNUSED(queue); +static void dolphin_reset_butthurt_timer(Dolphin* dolphin) { + uint32_t period_ticks = BUTTHURT_INCREASE_PERIOD_TICKS; + if(period_ticks > 0) { + furi_event_loop_timer_start(dolphin->butthurt_timer, period_ticks); + } else { + furi_event_loop_timer_stop(dolphin->butthurt_timer); + } +} + +static bool dolphin_process_event(FuriEventLoopObject* object, void* context) { + UNUSED(object); Dolphin* dolphin = context; DolphinEvent event; @@ -206,9 +225,7 @@ static bool dolphin_process_event(FuriMessageQueue* queue, void* context) { DolphinPubsubEvent event = DolphinPubsubEventUpdate; furi_pubsub_publish(dolphin->pubsub, &event); - if(BUTTHURT_INCREASE_PERIOD_TICKS > 0) { - furi_event_loop_timer_start(dolphin->butthurt_timer, BUTTHURT_INCREASE_PERIOD_TICKS); - } + dolphin_reset_butthurt_timer(dolphin); furi_event_loop_timer_start(dolphin->flush_timer, FLUSH_TIMEOUT_TICKS); } else if(event.type == DolphinEventTypeStats) { @@ -220,12 +237,17 @@ static bool dolphin_process_event(FuriMessageQueue* queue, void* context) { !dolphin_state_xp_to_levelup(dolphin->state->data.icounter); } else if(event.type == DolphinEventTypeFlush) { + dolphin_flush_timer_callback(dolphin); furi_event_loop_timer_start(dolphin->flush_timer, FLUSH_TIMEOUT_TICKS); } else if(event.type == DolphinEventTypeLevel) { dolphin_state_increase_level(dolphin->state); furi_event_loop_timer_start(dolphin->flush_timer, FLUSH_TIMEOUT_TICKS); + } else if(event.type == DolphinEventTypeReloadState) { + dolphin_state_load(dolphin->state); + dolphin_reset_butthurt_timer(dolphin); + } else { furi_crash(); } @@ -235,6 +257,32 @@ static bool dolphin_process_event(FuriMessageQueue* queue, void* context) { return true; } +static void dolphin_storage_callback(const void* message, void* context) { + furi_assert(context); + Dolphin* dolphin = context; + const StorageEvent* event = message; + + if(event->type == StorageEventTypeCardMount) { + DolphinEvent event = { + .type = DolphinEventTypeReloadState, + }; + + dolphin_event_send_async(dolphin, &event); + } +} + +static void dolphin_init_state(Dolphin* dolphin) { + Storage* storage = furi_record_open(RECORD_STORAGE); + furi_pubsub_subscribe(storage_get_pubsub(storage), dolphin_storage_callback, dolphin); + + if(storage_sd_status(storage) != FSE_OK) { + FURI_LOG_D(TAG, "SD Card not ready, skipping state"); + return; + } + + dolphin_state_load(dolphin->state); +} + // Application thread int32_t dolphin_srv(void* p) { @@ -250,18 +298,16 @@ int32_t dolphin_srv(void* p) { Dolphin* dolphin = dolphin_alloc(); furi_record_create(RECORD_DOLPHIN, dolphin); - dolphin_state_load(dolphin->state); + dolphin_init_state(dolphin); - furi_event_loop_message_queue_subscribe( + furi_event_loop_subscribe_message_queue( dolphin->event_loop, dolphin->event_queue, FuriEventLoopEventIn, dolphin_process_event, dolphin); - if(BUTTHURT_INCREASE_PERIOD_TICKS > 0) { - furi_event_loop_timer_start(dolphin->butthurt_timer, BUTTHURT_INCREASE_PERIOD_TICKS); - } + dolphin_reset_butthurt_timer(dolphin); furi_event_loop_timer_start(dolphin->clear_limits_timer, CLEAR_LIMITS_PERIOD_TICKS); furi_event_loop_tick_set( diff --git a/applications/services/dolphin/dolphin.h b/applications/services/dolphin/dolphin.h index 01da7f3f2..e66113021 100644 --- a/applications/services/dolphin/dolphin.h +++ b/applications/services/dolphin/dolphin.h @@ -45,6 +45,8 @@ void dolphin_upgrade_level(Dolphin* dolphin); FuriPubSub* dolphin_get_pubsub(Dolphin* dolphin); +void dolphin_reload_state(Dolphin* dolphin); + #ifdef __cplusplus } #endif diff --git a/applications/services/dolphin/dolphin_i.h b/applications/services/dolphin/dolphin_i.h index d4add808a..6a6b3dfd8 100644 --- a/applications/services/dolphin/dolphin_i.h +++ b/applications/services/dolphin/dolphin_i.h @@ -12,6 +12,7 @@ typedef enum { DolphinEventTypeStats, DolphinEventTypeFlush, DolphinEventTypeLevel, + DolphinEventTypeReloadState, } DolphinEventType; typedef struct { diff --git a/applications/services/dolphin/helpers/dolphin_state.c b/applications/services/dolphin/helpers/dolphin_state.c index b385bb315..7893737d2 100644 --- a/applications/services/dolphin/helpers/dolphin_state.c +++ b/applications/services/dolphin/helpers/dolphin_state.c @@ -1,10 +1,10 @@ #include "dolphin_state.h" -#include "dolphin/helpers/dolphin_deed.h" +#include "dolphin_state_filename.h" -#include -#include #include #include + +#include #include #define TAG "DolphinState" @@ -25,29 +25,28 @@ void dolphin_state_free(DolphinState* dolphin_state) { free(dolphin_state); } -bool dolphin_state_save(DolphinState* dolphin_state) { +void dolphin_state_save(DolphinState* dolphin_state) { if(!dolphin_state->dirty) { - return true; + return; } - bool result = saved_struct_save( + bool success = saved_struct_save( DOLPHIN_STATE_PATH, &dolphin_state->data, sizeof(DolphinStoreData), DOLPHIN_STATE_HEADER_MAGIC, DOLPHIN_STATE_HEADER_VERSION); - if(result) { + if(success) { FURI_LOG_I(TAG, "State saved"); dolphin_state->dirty = false; + } else { FURI_LOG_E(TAG, "Failed to save state"); } - - return result; } -bool dolphin_state_load(DolphinState* dolphin_state) { +void dolphin_state_load(DolphinState* dolphin_state) { bool success = saved_struct_load( DOLPHIN_STATE_PATH, &dolphin_state->data, @@ -63,12 +62,12 @@ bool dolphin_state_load(DolphinState* dolphin_state) { } if(!success) { - FURI_LOG_W(TAG, "Reset dolphin-state"); - memset(dolphin_state, 0, sizeof(*dolphin_state)); - dolphin_state->dirty = true; - } + FURI_LOG_W(TAG, "Reset Dolphin state"); + memset(dolphin_state, 0, sizeof(DolphinState)); - return success; + dolphin_state->dirty = true; + // dolphin_state_save(dolphin_state); + } } uint64_t dolphin_state_timestamp(void) { diff --git a/applications/services/dolphin/helpers/dolphin_state.h b/applications/services/dolphin/helpers/dolphin_state.h index c095b9331..ab27ab082 100644 --- a/applications/services/dolphin/helpers/dolphin_state.h +++ b/applications/services/dolphin/helpers/dolphin_state.h @@ -1,16 +1,15 @@ #pragma once -#include "dolphin_deed.h" #include #include #include +#include "dolphin_deed.h" + #ifdef __cplusplus extern "C" { #endif -#define DOLPHIN_STATE_PATH CFG_PATH("dolphin.state") - extern const uint32_t DOLPHIN_LEVELS[]; extern const size_t DOLPHIN_LEVEL_COUNT; @@ -37,9 +36,9 @@ DolphinState* dolphin_state_alloc(void); void dolphin_state_free(DolphinState* dolphin_state); -bool dolphin_state_save(DolphinState* dolphin_state); +void dolphin_state_save(DolphinState* dolphin_state); -bool dolphin_state_load(DolphinState* dolphin_state); +void dolphin_state_load(DolphinState* dolphin_state); void dolphin_state_clear_limits(DolphinState* dolphin_state); diff --git a/applications/services/dolphin/helpers/dolphin_state_filename.h b/applications/services/dolphin/helpers/dolphin_state_filename.h new file mode 100644 index 000000000..e6d822c5b --- /dev/null +++ b/applications/services/dolphin/helpers/dolphin_state_filename.h @@ -0,0 +1,5 @@ +#pragma once + +#define DOLPHIN_STATE_FILE_NAME ".dolphin.state" + +#define DOLPHIN_STATE_PATH INT_PATH(DOLPHIN_STATE_FILE_NAME) diff --git a/applications/services/expansion/application.fam b/applications/services/expansion/application.fam index b489cd235..dbdde0a52 100644 --- a/applications/services/expansion/application.fam +++ b/applications/services/expansion/application.fam @@ -5,8 +5,6 @@ App( cdefines=["SRV_EXPANSION"], sdk_headers=[ "expansion.h", - "expansion_i.h", - "expansion_settings.h", ], requires=["rpc_start"], provides=["expansion_settings"], diff --git a/applications/services/expansion/expansion.c b/applications/services/expansion/expansion.c index 9b0b31cf7..2b0c5b27a 100644 --- a/applications/services/expansion/expansion.c +++ b/applications/services/expansion/expansion.c @@ -1,9 +1,9 @@ #include "expansion.h" -#include "expansion_i.h" #include #include +#include #include #include "expansion_worker.h" @@ -25,6 +25,7 @@ typedef enum { ExpansionMessageTypeEnable, ExpansionMessageTypeDisable, ExpansionMessageTypeSetListenSerial, + ExpansionMessageTypeReloadSettings, ExpansionMessageTypeModuleConnected, ExpansionMessageTypeModuleDisconnected, ExpansionMessageTypeConnectionEstablished, @@ -32,10 +33,8 @@ typedef enum { } ExpansionMessageType; typedef union { - union { - FuriHalSerialId serial_id; - bool* is_connected; - }; + FuriHalSerialId serial_id; + bool* is_connected; } ExpansionMessageData; typedef struct { @@ -50,8 +49,6 @@ struct Expansion { FuriHalSerialId serial_id; ExpansionWorker* worker; ExpansionState state; - - ExpansionSettings settings; }; static const char* const expansion_uart_names[] = { @@ -103,9 +100,12 @@ static void return; } - if(instance->settings.uart_index < FuriHalSerialIdMax) { + ExpansionSettings settings; + expansion_settings_load(&settings); + + if(settings.uart_index < FuriHalSerialIdMax) { instance->state = ExpansionStateEnabled; - instance->serial_id = instance->settings.uart_index; + instance->serial_id = settings.uart_index; furi_hal_serial_control_set_expansion_callback( instance->serial_id, expansion_detect_callback, instance); @@ -116,7 +116,6 @@ static void static void expansion_control_handler_disable(Expansion* instance, const ExpansionMessageData* data) { UNUSED(data); - if(instance->state == ExpansionStateDisabled) { return; } else if( @@ -136,10 +135,12 @@ static void static void expansion_control_handler_set_listen_serial( Expansion* instance, const ExpansionMessageData* data) { - furi_check(data->serial_id < FuriHalSerialIdMax); + if(instance->state != ExpansionStateDisabled && instance->serial_id == data->serial_id) { + return; - if(instance->state == ExpansionStateRunning || - instance->state == ExpansionStateConnectionEstablished) { + } else if( + instance->state == ExpansionStateRunning || + instance->state == ExpansionStateConnectionEstablished) { expansion_worker_stop(instance->worker); expansion_worker_free(instance->worker); @@ -156,6 +157,26 @@ static void expansion_control_handler_set_listen_serial( FURI_LOG_D(TAG, "Listen serial changed to %s", expansion_uart_names[instance->serial_id]); } +static void expansion_control_handler_reload_settings( + Expansion* instance, + const ExpansionMessageData* data) { + UNUSED(data); + + ExpansionSettings settings; + expansion_settings_load(&settings); + + if(settings.uart_index < FuriHalSerialIdMax) { + const ExpansionMessageData data = { + .serial_id = settings.uart_index, + }; + + expansion_control_handler_set_listen_serial(instance, &data); + + } else { + expansion_control_handler_disable(instance, NULL); + } +} + static void expansion_control_handler_module_connected( Expansion* instance, const ExpansionMessageData* data) { @@ -211,6 +232,7 @@ static const ExpansionControlHandler expansion_control_handlers[] = { [ExpansionMessageTypeEnable] = expansion_control_handler_enable, [ExpansionMessageTypeDisable] = expansion_control_handler_disable, [ExpansionMessageTypeSetListenSerial] = expansion_control_handler_set_listen_serial, + [ExpansionMessageTypeReloadSettings] = expansion_control_handler_reload_settings, [ExpansionMessageTypeModuleConnected] = expansion_control_handler_module_connected, [ExpansionMessageTypeModuleDisconnected] = expansion_control_handler_module_disconnected, [ExpansionMessageTypeConnectionEstablished] = expansion_control_handler_connection_established, @@ -249,6 +271,22 @@ static Expansion* expansion_alloc(void) { return instance; } +static void expansion_storage_callback(const void* message, void* context) { + furi_assert(context); + + const StorageEvent* event = message; + Expansion* instance = context; + + if(event->type == StorageEventTypeCardMount) { + ExpansionMessage em = { + .type = ExpansionMessageTypeReloadSettings, + .api_lock = NULL, + }; + + furi_check(furi_message_queue_put(instance->queue, &em, FuriWaitForever) == FuriStatusOk); + } +} + void expansion_on_system_start(void* arg) { UNUSED(arg); @@ -256,7 +294,14 @@ void expansion_on_system_start(void* arg) { furi_record_create(RECORD_EXPANSION, instance); furi_thread_start(instance->thread); - expansion_settings_load(&instance->settings); + Storage* storage = furi_record_open(RECORD_STORAGE); + furi_pubsub_subscribe(storage_get_pubsub(storage), expansion_storage_callback, instance); + + if(storage_sd_status(storage) != FSE_OK) { + FURI_LOG_D(TAG, "SD Card not ready, skipping settings"); + return; + } + expansion_enable(instance); } @@ -315,7 +360,3 @@ void expansion_set_listen_serial(Expansion* instance, FuriHalSerialId serial_id) furi_message_queue_put(instance->queue, &message, FuriWaitForever); api_lock_wait_unlock_and_free(message.api_lock); } - -ExpansionSettings* expansion_get_settings(Expansion* instance) { - return &instance->settings; -} diff --git a/applications/services/expansion/expansion_i.h b/applications/services/expansion/expansion_i.h deleted file mode 100644 index b4be4b0d6..000000000 --- a/applications/services/expansion/expansion_i.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "expansion_settings.h" -#include "expansion.h" - -#ifdef __cplusplus -extern "C" { -#endif - -ExpansionSettings* expansion_get_settings(Expansion* instance); - -#ifdef __cplusplus -} -#endif diff --git a/applications/services/expansion/expansion_settings.c b/applications/services/expansion/expansion_settings.c index 342573697..d48a40a33 100644 --- a/applications/services/expansion/expansion_settings.c +++ b/applications/services/expansion/expansion_settings.c @@ -5,25 +5,39 @@ #include "expansion_settings_filename.h" +#define TAG "ExpansionSettings" + #define EXPANSION_SETTINGS_VERSION (0) #define EXPANSION_SETTINGS_MAGIC (0xEA) -bool expansion_settings_load(ExpansionSettings* settings) { +void expansion_settings_load(ExpansionSettings* settings) { furi_assert(settings); - return saved_struct_load( + + const bool success = saved_struct_load( EXPANSION_SETTINGS_PATH, settings, sizeof(ExpansionSettings), EXPANSION_SETTINGS_MAGIC, EXPANSION_SETTINGS_VERSION); + + if(!success) { + FURI_LOG_W(TAG, "Failed to load file, using defaults"); + memset(settings, 0, sizeof(ExpansionSettings)); + // expansion_settings_save(settings); + } } -bool expansion_settings_save(const ExpansionSettings* settings) { +void expansion_settings_save(const ExpansionSettings* settings) { furi_assert(settings); - return saved_struct_save( + + const bool success = saved_struct_save( EXPANSION_SETTINGS_PATH, settings, sizeof(ExpansionSettings), EXPANSION_SETTINGS_MAGIC, EXPANSION_SETTINGS_VERSION); + + if(!success) { + FURI_LOG_E(TAG, "Failed to save file"); + } } diff --git a/applications/services/expansion/expansion_settings.h b/applications/services/expansion/expansion_settings.h index 38e9f8d02..4594918e3 100644 --- a/applications/services/expansion/expansion_settings.h +++ b/applications/services/expansion/expansion_settings.h @@ -25,18 +25,16 @@ typedef struct { /** * @brief Load expansion module support settings from file. * - * @param[out] settings pointer to an ExpansionSettings instance to load settings into. - * @returns true if the settings were successfully loaded, false otherwise. + * @param[in,out] settings pointer to an ExpansionSettings instance to load settings into. */ -bool expansion_settings_load(ExpansionSettings* settings); +void expansion_settings_load(ExpansionSettings* settings); /** * @brief Save expansion module support settings to file. * * @param[in] settings pointer to an ExpansionSettings instance to save settings from. - * @returns true if the settings were successfully saved, false otherwise. */ -bool expansion_settings_save(const ExpansionSettings* settings); +void expansion_settings_save(const ExpansionSettings* settings); #ifdef __cplusplus } diff --git a/applications/services/expansion/expansion_settings_filename.h b/applications/services/expansion/expansion_settings_filename.h index 586f775c6..5c52bb25d 100644 --- a/applications/services/expansion/expansion_settings_filename.h +++ b/applications/services/expansion/expansion_settings_filename.h @@ -6,4 +6,6 @@ /** * @brief File name used for expansion settings. */ -#define EXPANSION_SETTINGS_PATH CFG_PATH("expansion.settings") +#define EXPANSION_SETTINGS_FILE_NAME ".expansion.settings" + +#define EXPANSION_SETTINGS_PATH INT_PATH(EXPANSION_SETTINGS_FILE_NAME) diff --git a/applications/services/gui/application.fam b/applications/services/gui/application.fam index b7dd18baa..b24f5bbb6 100644 --- a/applications/services/gui/application.fam +++ b/applications/services/gui/application.fam @@ -19,6 +19,7 @@ App( "view_holder.h", "modules/button_menu.h", "modules/byte_input.h", + "modules/number_input.h", "modules/popup.h", "modules/text_input.h", "modules/widget.h", diff --git a/applications/services/gui/gui.c b/applications/services/gui/gui.c index 812bf1c04..0f5ed61e9 100644 --- a/applications/services/gui/gui.c +++ b/applications/services/gui/gui.c @@ -1,8 +1,9 @@ -#include #include "gui_i.h" #include + #include #include +#include #define TAG "GuiSrv" @@ -628,7 +629,6 @@ Gui* gui_alloc(void) { gui->ascii_events = furi_record_open(RECORD_ASCII_EVENTS); furi_pubsub_subscribe(gui->input_events, gui_input_events_callback, gui); - furi_check(gui->ascii_events); furi_pubsub_subscribe(gui->ascii_events, gui_ascii_events_callback, gui); Storage* storage = furi_record_open(RECORD_STORAGE); diff --git a/applications/services/gui/icon_i.h b/applications/services/gui/icon_i.h index 46ceef327..e33cdbf23 100644 --- a/applications/services/gui/icon_i.h +++ b/applications/services/gui/icon_i.h @@ -6,8 +6,6 @@ #pragma once #include -#include "icon.h" - struct Icon { const uint16_t width; const uint16_t height; diff --git a/applications/services/gui/modules/file_browser_worker.c b/applications/services/gui/modules/file_browser_worker.c index a81689637..87e4c6041 100644 --- a/applications/services/gui/modules/file_browser_worker.c +++ b/applications/services/gui/modules/file_browser_worker.c @@ -15,7 +15,7 @@ #define TAG "BrowserWorker" #define ASSETS_DIR "assets" -#define BROWSER_ROOT STORAGE_ANY_PATH_PREFIX +#define BROWSER_ROOT STORAGE_EXT_PATH_PREFIX #define FILE_NAME_LEN_MAX 254 #define LONG_LOAD_THRESHOLD 100 @@ -137,7 +137,7 @@ static bool browser_filter_by_name(BrowserWorker* browser, FuriString* name, boo if((furi_string_empty(ext)) || (furi_string_cmp_str(ext, "*") == 0)) { return true; } - if(furi_string_end_with(name, ext)) { + if(furi_string_end_withi(name, ext)) { return true; } } diff --git a/applications/services/gui/modules/number_input.c b/applications/services/gui/modules/number_input.c new file mode 100644 index 000000000..058710d51 --- /dev/null +++ b/applications/services/gui/modules/number_input.c @@ -0,0 +1,449 @@ +#include "number_input.h" + +#include +#include +#include + +struct NumberInput { + View* view; +}; + +typedef struct { + const char text; + const size_t x; + const size_t y; +} NumberInputKey; + +typedef struct { + FuriString* header; + FuriString* text_buffer; + + int32_t current_number; + int32_t max_value; + int32_t min_value; + + NumberInputCallback callback; + void* callback_context; + + size_t selected_row; + size_t selected_column; +} NumberInputModel; + +static const size_t keyboard_origin_x = 7; +static const size_t keyboard_origin_y = 31; +static const size_t keyboard_row_count = 2; +static const char enter_symbol = '\r'; +static const char backspace_symbol = '\b'; +static const char sign_symbol = '-'; + +static const NumberInputKey keyboard_keys_row_1[] = { + {'0', 0, 12}, + {'1', 11, 12}, + {'2', 22, 12}, + {'3', 33, 12}, + {'4', 44, 12}, + {backspace_symbol, 100, 3}, +}; + +static const NumberInputKey keyboard_keys_row_2[] = { + {'5', 0, 26}, + {'6', 11, 26}, + {'7', 22, 26}, + {'8', 33, 26}, + {'9', 44, 26}, + {sign_symbol, 55, 17}, + {enter_symbol, 95, 17}, +}; + +static size_t number_input_get_row_size(size_t row_index) { + size_t row_size = 0; + + switch(row_index + 1) { + case 1: + row_size = COUNT_OF(keyboard_keys_row_1); + break; + case 2: + row_size = COUNT_OF(keyboard_keys_row_2); + break; + default: + furi_crash(); + } + + return row_size; +} + +static const NumberInputKey* number_input_get_row(size_t row_index) { + const NumberInputKey* row = NULL; + + switch(row_index + 1) { + case 1: + row = keyboard_keys_row_1; + break; + case 2: + row = keyboard_keys_row_2; + break; + default: + furi_crash(); + } + + return row; +} + +static void number_input_draw_input(Canvas* canvas, NumberInputModel* model) { + const size_t text_x = 8; + const size_t text_y = 25; + + elements_slightly_rounded_frame(canvas, 4, 14, 120, 15); + + canvas_draw_str(canvas, text_x, text_y, furi_string_get_cstr(model->text_buffer)); +} + +static bool number_input_use_sign(NumberInputModel* model) { + //only show sign button if allowed number range needs it + if(model->min_value < 0 && model->max_value >= 0) { + return true; + } + return false; +} + +static void number_input_backspace_cb(NumberInputModel* model) { + size_t text_length = furi_string_utf8_length(model->text_buffer); + if(text_length < 1 || (text_length < 2 && model->current_number <= 0)) { + return; + } + furi_string_set_strn( + model->text_buffer, furi_string_get_cstr(model->text_buffer), text_length - 1); + model->current_number = strtol(furi_string_get_cstr(model->text_buffer), NULL, 10); +} + +static void number_input_handle_up(NumberInputModel* model) { + if(model->selected_row > 0) { + model->selected_row--; + if(model->selected_column > number_input_get_row_size(model->selected_row) - 1) { + model->selected_column = number_input_get_row_size(model->selected_row) - 1; + } + } +} + +static void number_input_handle_down(NumberInputModel* model) { + if(model->selected_row < keyboard_row_count - 1) { + if(model->selected_column >= number_input_get_row_size(model->selected_row) - 1) { + model->selected_column = number_input_get_row_size(model->selected_row + 1) - 1; + } + model->selected_row += 1; + } + const NumberInputKey* keys = number_input_get_row(model->selected_row); + if(keys[model->selected_column].text == sign_symbol && !number_input_use_sign(model)) { + model->selected_column--; + } +} + +static void number_input_handle_left(NumberInputModel* model) { + if(model->selected_column > 0) { + model->selected_column--; + } else { + model->selected_column = number_input_get_row_size(model->selected_row) - 1; + } + const NumberInputKey* keys = number_input_get_row(model->selected_row); + if(keys[model->selected_column].text == sign_symbol && !number_input_use_sign(model)) { + model->selected_column--; + } +} + +static void number_input_handle_right(NumberInputModel* model) { + if(model->selected_column < number_input_get_row_size(model->selected_row) - 1) { + model->selected_column++; + } else { + model->selected_column = 0; + } + const NumberInputKey* keys = number_input_get_row(model->selected_row); + if(keys[model->selected_column].text == sign_symbol && !number_input_use_sign(model)) { + model->selected_column++; + } +} + +static bool is_number_too_large(NumberInputModel* model) { + int64_t value = strtoll(furi_string_get_cstr(model->text_buffer), NULL, 10); + if(value > (int64_t)model->max_value) { + return true; + } + return false; +} + +static bool is_number_too_small(NumberInputModel* model) { + int64_t value = strtoll(furi_string_get_cstr(model->text_buffer), NULL, 10); + if(value < (int64_t)model->min_value) { + return true; + } + return false; +} + +static void number_input_sign(NumberInputModel* model) { + int32_t number = strtol(furi_string_get_cstr(model->text_buffer), NULL, 10); + if(number == 0 && furi_string_cmp_str(model->text_buffer, "-") != 0) { + furi_string_set_str(model->text_buffer, "-"); + return; + } + number = number * -1; + furi_string_printf(model->text_buffer, "%ld", number); + if(is_number_too_large(model) || is_number_too_small(model)) { + furi_string_printf(model->text_buffer, "%ld", model->current_number); + return; + } + model->current_number = strtol(furi_string_get_cstr(model->text_buffer), NULL, 10); + if(model->current_number == 0) { + furi_string_set_str(model->text_buffer, ""); //show empty if 0, better for usability + } +} + +static void number_input_add_digit(NumberInputModel* model, char* newChar) { + furi_string_cat_str(model->text_buffer, newChar); + if((model->max_value >= 0 && is_number_too_large(model)) || + (model->min_value < 0 && is_number_too_small(model))) { + //you still need to be able to type invalid numbers in some cases to reach valid numbers on later keypress + furi_string_printf(model->text_buffer, "%ld", model->current_number); + return; + } + model->current_number = strtol(furi_string_get_cstr(model->text_buffer), NULL, 10); + if(model->current_number == 0) { + furi_string_set(model->text_buffer, "0"); + } +} + +static void number_input_handle_ok(NumberInputModel* model) { + char selected = number_input_get_row(model->selected_row)[model->selected_column].text; + char temp_str[2] = {selected, '\0'}; + if(selected == enter_symbol) { + if(is_number_too_large(model) || is_number_too_small(model)) { + return; //Do nothing if number outside allowed range + } + model->current_number = strtol(furi_string_get_cstr(model->text_buffer), NULL, 10); + model->callback(model->callback_context, model->current_number); + } else if(selected == backspace_symbol) { + number_input_backspace_cb(model); + } else if(selected == sign_symbol) { + number_input_sign(model); + } else { + number_input_add_digit(model, temp_str); + } +} + +static void number_input_view_draw_callback(Canvas* canvas, void* _model) { + NumberInputModel* model = _model; + + number_input_draw_input(canvas, model); + + if(!furi_string_empty(model->header)) { + canvas_set_font(canvas, FontSecondary); + canvas_draw_str(canvas, 2, 9, furi_string_get_cstr(model->header)); + } + canvas_set_font(canvas, FontKeyboard); + // Draw keyboard + for(size_t row = 0; row < keyboard_row_count; row++) { + const size_t column_count = number_input_get_row_size(row); + const NumberInputKey* keys = number_input_get_row(row); + + for(size_t column = 0; column < column_count; column++) { + if(keys[column].text == sign_symbol && !number_input_use_sign(model)) { + continue; + } + + if(keys[column].text == enter_symbol) { + if(is_number_too_small(model) || is_number_too_large(model)) { + //in some cases you need to be able to type a number smaller/larger than the limits (expl. min = 50, clear all and editor must allow to type 9 and later 0 for 90) + if(model->selected_row == row && model->selected_column == column) { + canvas_draw_icon( + canvas, + keyboard_origin_x + keys[column].x, + keyboard_origin_y + keys[column].y, + &I_KeySaveBlockedSelected_22x11); + } else { + canvas_draw_icon( + canvas, + keyboard_origin_x + keys[column].x, + keyboard_origin_y + keys[column].y, + &I_KeySaveBlocked_22x11); + } + } else { + if(model->selected_row == row && model->selected_column == column) { + canvas_draw_icon( + canvas, + keyboard_origin_x + keys[column].x, + keyboard_origin_y + keys[column].y, + &I_KeySaveSelected_22x11); + } else { + canvas_draw_icon( + canvas, + keyboard_origin_x + keys[column].x, + keyboard_origin_y + keys[column].y, + &I_KeySave_22x11); + } + } + } else if(keys[column].text == backspace_symbol) { + if(model->selected_row == row && model->selected_column == column) { + canvas_draw_icon( + canvas, + keyboard_origin_x + keys[column].x, + keyboard_origin_y + keys[column].y, + &I_KeyBackspaceSelected_17x11); + } else { + canvas_draw_icon( + canvas, + keyboard_origin_x + keys[column].x, + keyboard_origin_y + keys[column].y, + &I_KeyBackspace_17x11); + } + } else if(keys[column].text == sign_symbol) { + if(model->selected_row == row && model->selected_column == column) { + canvas_draw_icon( + canvas, + keyboard_origin_x + keys[column].x, + keyboard_origin_y + keys[column].y, + &I_KeySignSelected_21x11); + } else { + canvas_draw_icon( + canvas, + keyboard_origin_x + keys[column].x, + keyboard_origin_y + keys[column].y, + &I_KeySign_21x11); + } + } else { + if(model->selected_row == row && model->selected_column == column) { + elements_slightly_rounded_box( + canvas, + keyboard_origin_x + keys[column].x - 3, + keyboard_origin_y + keys[column].y - 10, + 11, + 13); + canvas_set_color(canvas, ColorWhite); + } + + canvas_draw_glyph( + canvas, + keyboard_origin_x + keys[column].x, + keyboard_origin_y + keys[column].y, + keys[column].text); + canvas_set_color(canvas, ColorBlack); + } + } + } +} + +static bool number_input_view_input_callback(InputEvent* event, void* context) { + furi_assert(context); + NumberInput* number_input = context; + + bool consumed = false; + + // Fetch the model + NumberInputModel* model = view_get_model(number_input->view); + + if(event->type == InputTypeShort || event->type == InputTypeLong || + event->type == InputTypeRepeat) { + consumed = true; + switch(event->key) { + case InputKeyLeft: + number_input_handle_left(model); + break; + case InputKeyRight: + number_input_handle_right(model); + break; + case InputKeyUp: + number_input_handle_up(model); + break; + case InputKeyDown: + number_input_handle_down(model); + break; + case InputKeyOk: + number_input_handle_ok(model); + break; + default: + consumed = false; + break; + } + } + + // commit view + view_commit_model(number_input->view, consumed); + + return consumed; +} + +NumberInput* number_input_alloc(void) { + NumberInput* number_input = malloc(sizeof(NumberInput)); + number_input->view = view_alloc(); + view_set_context(number_input->view, number_input); + view_allocate_model(number_input->view, ViewModelTypeLocking, sizeof(NumberInputModel)); + view_set_draw_callback(number_input->view, number_input_view_draw_callback); + view_set_input_callback(number_input->view, number_input_view_input_callback); + + with_view_model( + number_input->view, + NumberInputModel * model, + { + model->header = furi_string_alloc(); + model->text_buffer = furi_string_alloc(); + }, + true); + + return number_input; +} + +void number_input_free(NumberInput* number_input) { + furi_check(number_input); + with_view_model( + number_input->view, + NumberInputModel * model, + { + furi_string_free(model->header); + furi_string_free(model->text_buffer); + }, + true); + view_free(number_input->view); + free(number_input); +} + +View* number_input_get_view(NumberInput* number_input) { + furi_check(number_input); + return number_input->view; +} + +void number_input_set_result_callback( + NumberInput* number_input, + NumberInputCallback callback, + void* callback_context, + int32_t current_number, + int32_t min_value, + int32_t max_value) { + furi_check(number_input); + + if(current_number != 0) { + current_number = CLAMP(current_number, max_value, min_value); + } + + with_view_model( + number_input->view, + NumberInputModel * model, + { + model->callback = callback; + model->callback_context = callback_context; + model->current_number = current_number; + if(current_number != 0) { + furi_string_printf(model->text_buffer, "%ld", current_number); + } else { + furi_string_set(model->text_buffer, ""); + } + model->min_value = min_value; + model->max_value = max_value; + }, + true); +} + +void number_input_set_header_text(NumberInput* number_input, const char* text) { + furi_check(number_input); + with_view_model( + number_input->view, + NumberInputModel * model, + { furi_string_set(model->header, text); }, + true); +} diff --git a/applications/services/gui/modules/number_input.h b/applications/services/gui/modules/number_input.h new file mode 100644 index 000000000..80e631e9b --- /dev/null +++ b/applications/services/gui/modules/number_input.h @@ -0,0 +1,69 @@ +/** + * @file number_input.h + * GUI: Integer string keyboard view module API + */ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** Number input anonymous structure */ +typedef struct NumberInput NumberInput; + +/** Callback to be called on save button press */ +typedef void (*NumberInputCallback)(void* context, int32_t number); + +/** Allocate and initialize Number input. + * + * This Number input is used to enter Numbers (Integers). + * + * @return NumberInput instance pointer + */ +NumberInput* number_input_alloc(void); + +/** Deinitialize and free byte input + * + * @param number_input Number input instance + */ +void number_input_free(NumberInput* number_input); + +/** Get byte input view + * + * @param number_input byte input instance + * + * @return View instance that can be used for embedding + */ +View* number_input_get_view(NumberInput* number_input); + +/** Set byte input result callback + * + * @param number_input byte input instance + * @param input_callback input callback fn + * @param callback_context callback context + * @param[in] current_number The current number + * @param min_value Min number value + * @param max_value Max number value + */ + +void number_input_set_result_callback( + NumberInput* number_input, + NumberInputCallback input_callback, + void* callback_context, + int32_t current_number, + int32_t min_value, + int32_t max_value); + +/** Set byte input header text + * + * @param number_input byte input instance + * @param text text to be shown + */ +void number_input_set_header_text(NumberInput* number_input, const char* text); + +#ifdef __cplusplus +} +#endif diff --git a/applications/services/gui/view_dispatcher.c b/applications/services/gui/view_dispatcher.c index 9e91c2c9c..4bef29350 100644 --- a/applications/services/gui/view_dispatcher.c +++ b/applications/services/gui/view_dispatcher.c @@ -2,6 +2,8 @@ #define TAG "ViewDispatcher" +#define VIEW_DISPATCHER_QUEUE_LEN (16U) + ViewDispatcher* view_dispatcher_alloc(void) { ViewDispatcher* view_dispatcher = malloc(sizeof(ViewDispatcher)); @@ -16,6 +18,35 @@ ViewDispatcher* view_dispatcher_alloc(void) { ViewDict_init(view_dispatcher->views); + view_dispatcher->event_loop = furi_event_loop_alloc(); + + view_dispatcher->input_queue = + furi_message_queue_alloc(VIEW_DISPATCHER_QUEUE_LEN, sizeof(InputEvent)); + furi_event_loop_subscribe_message_queue( + view_dispatcher->event_loop, + view_dispatcher->input_queue, + FuriEventLoopEventIn, + view_dispatcher_run_input_callback, + view_dispatcher); + + view_dispatcher->ascii_queue = + furi_message_queue_alloc(VIEW_DISPATCHER_QUEUE_LEN, sizeof(AsciiEvent)); + furi_event_loop_subscribe_message_queue( + view_dispatcher->event_loop, + view_dispatcher->ascii_queue, + FuriEventLoopEventIn, + view_dispatcher_run_ascii_callback, + view_dispatcher); + + view_dispatcher->event_queue = + furi_message_queue_alloc(VIEW_DISPATCHER_QUEUE_LEN, sizeof(uint32_t)); + furi_event_loop_subscribe_message_queue( + view_dispatcher->event_loop, + view_dispatcher->event_queue, + FuriEventLoopEventIn, + view_dispatcher_run_event_callback, + view_dispatcher); + return view_dispatcher; } @@ -31,57 +62,21 @@ void view_dispatcher_free(ViewDispatcher* view_dispatcher) { // Free ViewPort view_port_free(view_dispatcher->view_port); // Free internal queue - if(view_dispatcher->input_queue) { - furi_event_loop_message_queue_unsubscribe( - view_dispatcher->event_loop, view_dispatcher->input_queue); - furi_message_queue_free(view_dispatcher->input_queue); - } - if(view_dispatcher->ascii_queue) { - furi_event_loop_message_queue_unsubscribe( - view_dispatcher->event_loop, view_dispatcher->ascii_queue); - furi_message_queue_free(view_dispatcher->ascii_queue); - } - if(view_dispatcher->event_queue) { - furi_event_loop_message_queue_unsubscribe( - view_dispatcher->event_loop, view_dispatcher->event_queue); - furi_message_queue_free(view_dispatcher->event_queue); - } - if(view_dispatcher->event_loop) { - furi_event_loop_free(view_dispatcher->event_loop); - } + furi_event_loop_unsubscribe(view_dispatcher->event_loop, view_dispatcher->input_queue); + furi_event_loop_unsubscribe(view_dispatcher->event_loop, view_dispatcher->ascii_queue); + furi_event_loop_unsubscribe(view_dispatcher->event_loop, view_dispatcher->event_queue); + + furi_message_queue_free(view_dispatcher->input_queue); + furi_message_queue_free(view_dispatcher->ascii_queue); + furi_message_queue_free(view_dispatcher->event_queue); + + furi_event_loop_free(view_dispatcher->event_loop); // Free dispatcher free(view_dispatcher); } void view_dispatcher_enable_queue(ViewDispatcher* view_dispatcher) { - furi_check(view_dispatcher); - furi_check(view_dispatcher->event_loop == NULL); - - view_dispatcher->event_loop = furi_event_loop_alloc(); - - view_dispatcher->input_queue = furi_message_queue_alloc(16, sizeof(InputEvent)); - furi_event_loop_message_queue_subscribe( - view_dispatcher->event_loop, - view_dispatcher->input_queue, - FuriEventLoopEventIn, - view_dispatcher_run_input_callback, - view_dispatcher); - - view_dispatcher->ascii_queue = furi_message_queue_alloc(16, sizeof(AsciiEvent)); - furi_event_loop_message_queue_subscribe( - view_dispatcher->event_loop, - view_dispatcher->ascii_queue, - FuriEventLoopEventIn, - view_dispatcher_run_ascii_callback, - view_dispatcher); - - view_dispatcher->event_queue = furi_message_queue_alloc(16, sizeof(uint32_t)); - furi_event_loop_message_queue_subscribe( - view_dispatcher->event_loop, - view_dispatcher->event_queue, - FuriEventLoopEventIn, - view_dispatcher_run_event_callback, - view_dispatcher); + UNUSED(view_dispatcher); } void view_dispatcher_set_navigation_event_callback( @@ -114,14 +109,12 @@ void view_dispatcher_set_event_callback_context(ViewDispatcher* view_dispatcher, FuriEventLoop* view_dispatcher_get_event_loop(ViewDispatcher* view_dispatcher) { furi_check(view_dispatcher); - furi_check(view_dispatcher->event_loop); return view_dispatcher->event_loop; } void view_dispatcher_run(ViewDispatcher* view_dispatcher) { furi_check(view_dispatcher); - furi_check(view_dispatcher->event_loop); uint32_t tick_period = view_dispatcher->tick_period == 0 ? FuriWaitForever : view_dispatcher->tick_period; @@ -149,7 +142,6 @@ void view_dispatcher_run(ViewDispatcher* view_dispatcher) { void view_dispatcher_stop(ViewDispatcher* view_dispatcher) { furi_check(view_dispatcher); - furi_check(view_dispatcher->event_loop); furi_event_loop_stop(view_dispatcher->event_loop); } @@ -257,13 +249,9 @@ void view_dispatcher_draw_callback(Canvas* canvas, void* context) { void view_dispatcher_input_callback(InputEvent* event, void* context) { ViewDispatcher* view_dispatcher = context; - if(view_dispatcher->input_queue) { - furi_check( - furi_message_queue_put(view_dispatcher->input_queue, event, FuriWaitForever) == - FuriStatusOk); - } else { - view_dispatcher_handle_input(view_dispatcher, event); - } + furi_check( + furi_message_queue_put(view_dispatcher->input_queue, event, FuriWaitForever) == + FuriStatusOk); } bool view_dispatcher_ascii_callback(AsciiEvent* event, void* context) { @@ -271,13 +259,9 @@ bool view_dispatcher_ascii_callback(AsciiEvent* event, void* context) { // So instead ViewDispatcher tells ViewPort that all events are consumed // Then ViewDispatcher handles fallbacks the same way as ViewPort would have done ViewDispatcher* view_dispatcher = context; - if(view_dispatcher->ascii_queue) { - furi_check( - furi_message_queue_put(view_dispatcher->ascii_queue, event, FuriWaitForever) == - FuriStatusOk); - } else { - view_dispatcher_handle_ascii(view_dispatcher, event); - } + furi_check( + furi_message_queue_put(view_dispatcher->ascii_queue, event, FuriWaitForever) == + FuriStatusOk); return true; } @@ -400,7 +384,6 @@ void view_dispatcher_handle_custom_event(ViewDispatcher* view_dispatcher, uint32 void view_dispatcher_send_custom_event(ViewDispatcher* view_dispatcher, uint32_t event) { furi_check(view_dispatcher); - furi_check(view_dispatcher->event_loop); furi_check( furi_message_queue_put(view_dispatcher->event_queue, &event, FuriWaitForever) == @@ -436,9 +419,7 @@ void view_dispatcher_set_current_view(ViewDispatcher* view_dispatcher, View* vie view_port_update(view_dispatcher->view_port); } else { view_port_enabled_set(view_dispatcher->view_port, false); - if(view_dispatcher->event_loop) { - view_dispatcher_stop(view_dispatcher); - } + view_dispatcher_stop(view_dispatcher); } } @@ -453,10 +434,10 @@ void view_dispatcher_update(View* view, void* context) { } } -bool view_dispatcher_run_event_callback(FuriMessageQueue* queue, void* context) { +bool view_dispatcher_run_event_callback(FuriEventLoopObject* object, void* context) { furi_assert(context); ViewDispatcher* instance = context; - furi_assert(instance->event_queue == queue); + furi_assert(instance->event_queue == object); uint32_t event; furi_check(furi_message_queue_get(instance->event_queue, &event, 0) == FuriStatusOk); @@ -465,10 +446,10 @@ bool view_dispatcher_run_event_callback(FuriMessageQueue* queue, void* context) return true; } -bool view_dispatcher_run_input_callback(FuriMessageQueue* queue, void* context) { +bool view_dispatcher_run_input_callback(FuriEventLoopObject* object, void* context) { furi_assert(context); ViewDispatcher* instance = context; - furi_assert(instance->input_queue == queue); + furi_assert(instance->input_queue == object); InputEvent input; furi_check(furi_message_queue_get(instance->input_queue, &input, 0) == FuriStatusOk); @@ -477,10 +458,10 @@ bool view_dispatcher_run_input_callback(FuriMessageQueue* queue, void* context) return true; } -bool view_dispatcher_run_ascii_callback(FuriMessageQueue* queue, void* context) { +bool view_dispatcher_run_ascii_callback(FuriEventLoopObject* object, void* context) { furi_assert(context); ViewDispatcher* instance = context; - furi_assert(instance->ascii_queue == queue); + furi_assert(instance->ascii_queue == object); AsciiEvent ascii; furi_check(furi_message_queue_get(instance->ascii_queue, &ascii, 0) == FuriStatusOk); diff --git a/applications/services/gui/view_dispatcher.h b/applications/services/gui/view_dispatcher.h index 905c60975..9fbf89791 100644 --- a/applications/services/gui/view_dispatcher.h +++ b/applications/services/gui/view_dispatcher.h @@ -2,6 +2,14 @@ * @file view_dispatcher.h * @brief GUI: ViewDispatcher API * + * ViewDispatcher is used to connect several Views to a Gui instance, switch between them and handle various events. + * This is useful in applications featuring an advanced graphical user interface. + * + * Internally, ViewDispatcher employs a FuriEventLoop instance together with two separate + * message queues for input and custom event handling. See FuriEventLoop for more information. + * + * If no multi-view or complex event handling capabilities are required, consider using ViewHolder instead. + * * @warning Views added to a ViewDispatcher MUST NOT be in a ViewStack at the same time. */ @@ -40,6 +48,9 @@ typedef void (*ViewDispatcherTickEventCallback)(void* context); ViewDispatcher* view_dispatcher_alloc(void); /** Free ViewDispatcher instance + * + * @warning All added views MUST be removed using view_dispatcher_remove_view() + * before calling this function. * * @param view_dispatcher pointer to ViewDispatcher */ @@ -47,12 +58,13 @@ void view_dispatcher_free(ViewDispatcher* view_dispatcher); /** Enable queue support * - * Allocates event_loop, input and event message queues. Must be used with - * `view_dispatcher_run` + * @deprecated Do NOT use in new code and remove all calls to it from existing code. + * The queue support is now always enabled during construction. If no queue support + * is required, consider using ViewHolder instead. * * @param view_dispatcher ViewDispatcher instance */ -void view_dispatcher_enable_queue(ViewDispatcher* view_dispatcher); +FURI_DEPRECATED void view_dispatcher_enable_queue(ViewDispatcher* view_dispatcher); /** Send custom event * @@ -103,11 +115,11 @@ void view_dispatcher_set_event_callback_context(ViewDispatcher* view_dispatcher, /** Get event_loop instance * - * event_loop instance is allocated on `view_dispatcher_enable_queue` and used - * in view_dispatcher_run. + * Use the return value to connect additional supported primitives (message queues, timers, etc) + * to this ViewDispatcher instance's event loop. * - * You can add your objects into event_loop instance, but don't run the loop on - * your side as it will cause issues with input processing on dispatcher stop. + * @warning Do NOT call furi_event_loop_run() on the returned instance, it is done internally + * in the view_dispatcher_run() call. * * @param view_dispatcher ViewDispatcher instance * @@ -117,15 +129,14 @@ FuriEventLoop* view_dispatcher_get_event_loop(ViewDispatcher* view_dispatcher); /** Run ViewDispatcher * - * Use only after queue enabled + * This function will start the event loop and block until view_dispatcher_stop() is called + * or the current thread receives a FuriSignalExit signal. * * @param view_dispatcher ViewDispatcher instance */ void view_dispatcher_run(ViewDispatcher* view_dispatcher); /** Stop ViewDispatcher - * - * Use only after queue enabled * * @param view_dispatcher ViewDispatcher instance */ diff --git a/applications/services/gui/view_dispatcher_i.h b/applications/services/gui/view_dispatcher_i.h index 28c794b59..6b2db9b54 100644 --- a/applications/services/gui/view_dispatcher_i.h +++ b/applications/services/gui/view_dispatcher_i.h @@ -16,7 +16,6 @@ DICT_DEF2(ViewDict, uint32_t, M_DEFAULT_OPLIST, View*, M_PTR_OPLIST) // NOLINT struct ViewDispatcher { FuriEventLoop* event_loop; FuriMessageQueue* input_queue; - FuriMessageQueue* ascii_queue; FuriMessageQueue* event_queue; Gui* gui; @@ -33,6 +32,8 @@ struct ViewDispatcher { ViewDispatcherTickEventCallback tick_event_callback; uint32_t tick_period; void* event_context; + + FuriMessageQueue* ascii_queue; }; /** ViewPort Draw Callback */ @@ -63,10 +64,10 @@ void view_dispatcher_set_current_view(ViewDispatcher* view_dispatcher, View* vie void view_dispatcher_update(View* view, void* context); /** ViewDispatcher run event loop event callback */ -bool view_dispatcher_run_event_callback(FuriMessageQueue* queue, void* context); +bool view_dispatcher_run_event_callback(FuriEventLoopObject* object, void* context); /** ViewDispatcher run event loop input callback */ -bool view_dispatcher_run_input_callback(FuriMessageQueue* queue, void* context); +bool view_dispatcher_run_input_callback(FuriEventLoopObject* object, void* context); /** ViewDispatcher run event loop ascii callback */ -bool view_dispatcher_run_ascii_callback(FuriMessageQueue* queue, void* context); +bool view_dispatcher_run_ascii_callback(FuriEventLoopObject* object, void* context); diff --git a/applications/services/gui/view_holder.c b/applications/services/gui/view_holder.c index d00458507..6de5528a3 100644 --- a/applications/services/gui/view_holder.c +++ b/applications/services/gui/view_holder.c @@ -34,7 +34,8 @@ ViewHolder* view_holder_alloc(void) { } void view_holder_free(ViewHolder* view_holder) { - furi_assert(view_holder); + furi_check(view_holder); + furi_check(view_holder->view == NULL); if(view_holder->gui) { gui_remove_view_port(view_holder->gui, view_holder->view_port); @@ -50,12 +51,14 @@ void view_holder_free(ViewHolder* view_holder) { } void view_holder_set_view(ViewHolder* view_holder, View* view) { - furi_assert(view_holder); + furi_check(view_holder); + if(view_holder->view) { - if(view_holder->view->exit_callback) { - view_holder->view->exit_callback(view_holder->view->context); + while(view_holder->ongoing_input) { + furi_delay_tick(1); } + view_exit(view_holder->view); view_set_update_callback(view_holder->view, NULL); view_set_update_callback_context(view_holder->view, NULL); } @@ -63,12 +66,23 @@ void view_holder_set_view(ViewHolder* view_holder, View* view) { view_holder->view = view; if(view_holder->view) { + const ViewPortOrientation orientation = (ViewPortOrientation)view->orientation; + furi_assert(orientation < ViewPortOrientationMAX); + if(view_port_get_orientation(view_holder->view_port) != orientation) { + view_port_set_orientation(view_holder->view_port, orientation); + // we just rotated input keys, now it's time to sacrifice some input + view_holder->ongoing_input = 0; + } + view_set_update_callback(view_holder->view, view_holder_update); view_set_update_callback_context(view_holder->view, view_holder); - if(view_holder->view->enter_callback) { - view_holder->view->enter_callback(view_holder->view->context); - } + view_enter(view_holder->view); + view_port_enabled_set(view_holder->view_port, true); + view_port_update(view_holder->view_port); + + } else { + view_port_enabled_set(view_holder->view_port, false); } } @@ -76,7 +90,7 @@ void view_holder_set_free_callback( ViewHolder* view_holder, FreeCallback free_callback, void* free_context) { - furi_assert(view_holder); + furi_check(view_holder); view_holder->free_callback = free_callback; view_holder->free_context = free_context; } @@ -89,31 +103,22 @@ void view_holder_set_back_callback( ViewHolder* view_holder, BackCallback back_callback, void* back_context) { - furi_assert(view_holder); + furi_check(view_holder); view_holder->back_callback = back_callback; view_holder->back_context = back_context; } void view_holder_attach_to_gui(ViewHolder* view_holder, Gui* gui) { - furi_assert(gui); - furi_assert(view_holder); - view_holder->gui = gui; + furi_check(view_holder); + furi_check(view_holder->gui == NULL); + furi_check(gui); gui_add_view_port(gui, view_holder->view_port, GuiLayerFullscreen); -} - -void view_holder_start(ViewHolder* view_holder) { - view_port_enabled_set(view_holder->view_port, true); -} - -void view_holder_stop(ViewHolder* view_holder) { - while(view_holder->ongoing_input) - furi_delay_tick(1); - view_port_enabled_set(view_holder->view_port, false); + view_holder->gui = gui; } void view_holder_update(View* view, void* context) { - furi_assert(view); - furi_assert(context); + furi_check(view); + furi_check(context); ViewHolder* view_holder = context; if(view == view_holder->view) { @@ -121,6 +126,18 @@ void view_holder_update(View* view, void* context) { } } +void view_holder_send_to_front(ViewHolder* view_holder) { + furi_check(view_holder); + furi_check(view_holder->gui); + gui_view_port_send_to_front(view_holder->gui, view_holder->view_port); +} + +void view_holder_send_to_back(ViewHolder* view_holder) { + furi_check(view_holder); + furi_check(view_holder->gui); + gui_view_port_send_to_back(view_holder->gui, view_holder->view_port); +} + static void view_holder_draw_callback(Canvas* canvas, void* context) { ViewHolder* view_holder = context; if(view_holder->view) { diff --git a/applications/services/gui/view_holder.h b/applications/services/gui/view_holder.h index 90ce82b37..78dbfda0e 100644 --- a/applications/services/gui/view_holder.h +++ b/applications/services/gui/view_holder.h @@ -2,7 +2,10 @@ * @file view_holder.h * @brief GUI: ViewHolder API * - * @warning View added to a ViewHolder MUST NOT be in a ViewStack at the same time. + * ViewHolder is used to connect a single View to a Gui instance. This is useful in smaller applications + * with a simple user interface. If advanced view switching capabilites are required, consider using ViewDispatcher instead. + * + * @warning Views added to a ViewHolder MUST NOT be in a ViewStack at the same time. */ #pragma once @@ -22,7 +25,8 @@ typedef void (*FreeCallback)(void* free_context); /** * @brief Back callback type - * @warning comes from GUI thread + * + * @warning Will be called from the GUI thread */ typedef void (*BackCallback)(void* back_context); @@ -34,12 +38,17 @@ ViewHolder* view_holder_alloc(void); /** * @brief Free ViewHolder and call Free callback + * + * @warning The current view must be unset prior to freeing a ViewHolder instance. + * * @param view_holder pointer to ViewHolder */ void view_holder_free(ViewHolder* view_holder); /** * @brief Set view for ViewHolder + * + * Pass NULL as the view parameter to unset the current view. * * @param view_holder ViewHolder instance * @param view View instance @@ -59,13 +68,25 @@ void view_holder_set_free_callback( void* free_context); /** - * @brief Free callback context getter. Useful if your Free callback is a module destructor, so you can get an instance of the module using this method. + * @brief Free callback context getter. + * + * Useful if your Free callback is a module destructor, so you can get an instance of the module using this method. * * @param view_holder ViewHolder instance * @return void* free callback context */ void* view_holder_get_free_context(ViewHolder* view_holder); +/** + * @brief Set the back key callback. + * + * The callback function will be called if the user has pressed the Back key + * and the current view did not handle this event. + * + * @param view_holder ViewHolder instance + * @param back_callback pointer to the callback function + * @param back_context pointer to a user-specific object, can be NULL + */ void view_holder_set_back_callback( ViewHolder* view_holder, BackCallback back_callback, @@ -80,26 +101,27 @@ void view_holder_set_back_callback( void view_holder_attach_to_gui(ViewHolder* view_holder, Gui* gui); /** - * @brief Enable view processing - * - * @param view_holder - */ -void view_holder_start(ViewHolder* view_holder); - -/** - * @brief Disable view processing - * - * @param view_holder - */ -void view_holder_stop(ViewHolder* view_holder); - -/** View Update Handler + * @brief View Update Handler * - * @param view View Instance - * @param context ViewHolder instance + * @param view View Instance + * @param context ViewHolder instance */ void view_holder_update(View* view, void* context); +/** + * @brief Send ViewPort of this ViewHolder instance to front + * + * @param view_holder ViewHolder instance + */ +void view_holder_send_to_front(ViewHolder* view_holder); + +/** + * @brief Send ViewPort of this ViewHolder instance to back + * + * @param view_holder ViewHolder instance + */ +void view_holder_send_to_back(ViewHolder* view_holder); + #ifdef __cplusplus } #endif diff --git a/applications/services/loader/loader_applications.c b/applications/services/loader/loader_applications.c index 9b4b84ee9..aebb03d63 100644 --- a/applications/services/loader/loader_applications.c +++ b/applications/services/loader/loader_applications.c @@ -61,7 +61,6 @@ static LoaderApplicationsApp* loader_applications_app_alloc(void) { app->loading = loading_alloc(); view_holder_attach_to_gui(app->view_holder, app->gui); - view_holder_set_view(app->view_holder, loading_get_view(app->loading)); return app; } //-V773 @@ -152,7 +151,7 @@ static int32_t loader_applications_thread(void* p) { LoaderApplicationsApp* app = loader_applications_app_alloc(); // start loading animation - view_holder_start(app->view_holder); + view_holder_set_view(app->view_holder, loading_get_view(app->loading)); while(loader_applications_select_app(app)) { if(!furi_string_end_with(app->file_path, ".js")) { @@ -164,7 +163,7 @@ static int32_t loader_applications_thread(void* p) { } // stop loading animation - view_holder_stop(app->view_holder); + view_holder_set_view(app->view_holder, NULL); loader_applications_app_free(app); diff --git a/applications/services/loader/loader_menu.c b/applications/services/loader/loader_menu.c index 93d70bc09..8d80e89bc 100644 --- a/applications/services/loader/loader_menu.c +++ b/applications/services/loader/loader_menu.c @@ -63,13 +63,6 @@ static void loader_pubsub_callback(const void* message, void* context) { } } -static void loader_menu_set_view(LoaderMenu* loader_menu, View* view) { - view_holder_set_view(loader_menu->view_holder, view); - if(view) { - view_holder_update(view, loader_menu->view_holder); - } -} - static void loader_menu_dummy_draw(Canvas* canvas, void* context) { UNUSED(context); @@ -101,8 +94,7 @@ LoaderMenu* loader_menu_alloc(void (*closed_cb)(void*), void* context, bool sett loader_menu->view_holder = view_holder_alloc(); view_holder_attach_to_gui(loader_menu->view_holder, gui); view_holder_set_back_callback(loader_menu->view_holder, NULL, NULL); - loader_menu_set_view(loader_menu, loader_menu->dummy); - view_holder_start(loader_menu->view_holder); + view_holder_set_view(loader_menu->view_holder, loader_menu->dummy); loader_menu->loader = furi_record_open(RECORD_LOADER); loader_menu->subscription = furi_pubsub_subscribe( @@ -124,6 +116,7 @@ void loader_menu_free(LoaderMenu* loader_menu) { furi_thread_free(loader_menu->thread); } + view_holder_set_view(loader_menu->view_holder, NULL); view_holder_free(loader_menu->view_holder); furi_record_close(RECORD_GUI); @@ -181,10 +174,18 @@ static void loader_menu_settings_menu_callback(void* context, uint32_t index) { loader_menu_start(name); } +// Can't do this in GUI callbacks because now ViewHolder waits for ongoing +// input, and inputs are not processed because GUI is processing callbacks +static void loader_menu_set_view_pending(void* context, uint32_t arg) { + LoaderMenuApp* app = context; + view_holder_set_view(app->loader_menu->view_holder, (View*)arg); +} + static void loader_menu_switch_to_settings(void* context, uint32_t index) { UNUSED(index); LoaderMenuApp* app = context; - loader_menu_set_view(app->loader_menu, submenu_get_view(app->settings_menu)); + furi_timer_pending_callback( + loader_menu_set_view_pending, app, (uint32_t)submenu_get_view(app->settings_menu)); app->loader_menu->current_view = LoaderMenuViewSettings; } @@ -192,7 +193,8 @@ static void loader_menu_back(void* context) { LoaderMenuApp* app = context; if(app->loader_menu->current_view == LoaderMenuViewSettings && !app->loader_menu->settings_only) { - loader_menu_set_view(app->loader_menu, menu_get_view(app->primary_menu)); + furi_timer_pending_callback( + loader_menu_set_view_pending, app, (uint32_t)menu_get_view(app->primary_menu)); app->loader_menu->current_view = LoaderMenuViewPrimary; } else { furi_thread_flags_set(furi_thread_get_id(app->loader_menu->thread), 0); @@ -296,6 +298,8 @@ static void loader_menu_build_menu(LoaderMenuApp* app, LoaderMenu* menu) { furi_string_set(line, "125 kHz RFID"); } else if(furi_string_equal(line, "SubGHz")) { furi_string_set(line, "Sub-GHz"); + } else if(furi_string_equal(line, "Xtreme")) { + furi_string_set(line, "Momentum"); } } loader_menu_find_add_app(app, storage, line); @@ -363,7 +367,7 @@ static LoaderMenuApp* loader_menu_app_alloc(LoaderMenu* loader_menu) { View* view = app->loader_menu->current_view == LoaderMenuViewSettings ? submenu_get_view(app->settings_menu) : menu_get_view(app->primary_menu); - loader_menu_set_view(app->loader_menu, view); + view_holder_set_view(app->loader_menu->view_holder, view); view_holder_set_back_callback(app->loader_menu->view_holder, loader_menu_back, app); return app; @@ -371,7 +375,7 @@ static LoaderMenuApp* loader_menu_app_alloc(LoaderMenu* loader_menu) { static void loader_menu_app_free(LoaderMenuApp* app) { view_holder_set_back_callback(app->loader_menu->view_holder, NULL, NULL); - loader_menu_set_view(app->loader_menu, app->loader_menu->dummy); + view_holder_set_view(app->loader_menu->view_holder, app->loader_menu->dummy); if(!app->loader_menu->settings_only) { app->loader_menu->selected_primary = menu_get_selected_item(app->primary_menu); diff --git a/applications/services/loader/loader_menu.h b/applications/services/loader/loader_menu.h index cd0f311a7..28059bf4f 100644 --- a/applications/services/loader/loader_menu.h +++ b/applications/services/loader/loader_menu.h @@ -5,7 +5,7 @@ extern "C" { #endif -#define MAINMENU_APPS_PATH CFG_PATH("mainmenu_apps.txt") +#define MAINMENU_APPS_PATH INT_PATH(".mainmenu_apps.txt") typedef struct LoaderMenu LoaderMenu; diff --git a/applications/services/notification/application.fam b/applications/services/notification/application.fam index c93dc4d6c..82f94085a 100644 --- a/applications/services/notification/application.fam +++ b/applications/services/notification/application.fam @@ -8,5 +8,5 @@ App( provides=["notification_settings"], stack_size=int(1.5 * 1024), order=100, - sdk_headers=["notification.h", "notification_messages.h", "notification_app.h"], + sdk_headers=["notification.h", "notification_messages.h"], ) diff --git a/applications/services/notification/notification_app.c b/applications/services/notification/notification_app.c index 6efdcafd8..866d93de4 100644 --- a/applications/services/notification/notification_app.c +++ b/applications/services/notification/notification_app.c @@ -423,8 +423,8 @@ static void } } -static bool notification_save_settings(NotificationApp* app) { - return saved_struct_save( +static bool notification_load_settings(NotificationApp* app) { + return saved_struct_load( NOTIFICATION_SETTINGS_PATH, &app->settings, sizeof(NotificationSettings), @@ -432,8 +432,8 @@ static bool notification_save_settings(NotificationApp* app) { NOTIFICATION_SETTINGS_VERSION); } -static bool notification_load_settings(NotificationApp* app) { - return saved_struct_load( +static bool notification_save_settings(NotificationApp* app) { + return saved_struct_save( NOTIFICATION_SETTINGS_PATH, &app->settings, sizeof(NotificationSettings), @@ -471,26 +471,24 @@ static NotificationApp* notification_app_alloc(void) { app->settings.display_off_delay_ms = 30000; app->settings.vibro_on = true; - // malloc() also does memset(0), no need to init 0 values - _Static_assert(LayerInternal == 0, "need to init layer values"); - // app->display.value[LayerInternal] = 0x00; - // app->display.value[LayerNotification] = 0x00; - // app->display.index = LayerInternal; + app->display.value[LayerInternal] = 0x00; + app->display.value[LayerNotification] = 0x00; + app->display.index = LayerInternal; app->display.light = LightBacklight; - // app->led[0].value[LayerInternal] = 0x00; - // app->led[0].value[LayerNotification] = 0x00; - // app->led[0].index = LayerInternal; + app->led[0].value[LayerInternal] = 0x00; + app->led[0].value[LayerNotification] = 0x00; + app->led[0].index = LayerInternal; app->led[0].light = LightRed; - // app->led[1].value[LayerInternal] = 0x00; - // app->led[1].value[LayerNotification] = 0x00; - // app->led[1].index = LayerInternal; + app->led[1].value[LayerInternal] = 0x00; + app->led[1].value[LayerNotification] = 0x00; + app->led[1].index = LayerInternal; app->led[1].light = LightGreen; - // app->led[2].value[LayerInternal] = 0x00; - // app->led[2].value[LayerNotification] = 0x00; - // app->led[2].index = LayerInternal; + app->led[2].value[LayerInternal] = 0x00; + app->led[2].value[LayerNotification] = 0x00; + app->led[2].index = LayerInternal; app->led[2].light = LightBlue; app->settings.version = NOTIFICATION_SETTINGS_VERSION; @@ -505,12 +503,46 @@ static NotificationApp* notification_app_alloc(void) { return app; } +static void notification_storage_callback(const void* message, void* context) { + furi_assert(context); + NotificationApp* app = context; + const StorageEvent* event = message; + + if(event->type == StorageEventTypeCardMount) { + NotificationAppMessage m = { + .type = LoadSettingsMessage, + }; + + furi_check(furi_message_queue_put(app->queue, &m, FuriWaitForever) == FuriStatusOk); + } +} + +static void notification_apply_settings(NotificationApp* app) { + if(!notification_load_settings(app)) { + // notification_save_settings(app); + } + + notification_apply_lcd_contrast(app); +} + +static void notification_init_settings(NotificationApp* app) { + Storage* storage = furi_record_open(RECORD_STORAGE); + furi_pubsub_subscribe(storage_get_pubsub(storage), notification_storage_callback, app); + + if(storage_sd_status(storage) != FSE_OK) { + FURI_LOG_D(TAG, "SD Card not ready, skipping settings"); + return; + } + + notification_apply_settings(app); +} + // App int32_t notification_srv(void* p) { UNUSED(p); NotificationApp* app = notification_app_alloc(); - notification_load_settings(app); + notification_init_settings(app); notification_vibro_off(); notification_sound_off(); @@ -518,7 +550,6 @@ int32_t notification_srv(void* p) { notification_apply_internal_led_layer(&app->led[0], 0x00); notification_apply_internal_led_layer(&app->led[1], 0x00); notification_apply_internal_led_layer(&app->led[2], 0x00); - notification_apply_lcd_contrast(app); furi_record_create(RECORD_NOTIFICATION, app); @@ -536,6 +567,9 @@ int32_t notification_srv(void* p) { case SaveSettingsMessage: notification_save_settings(app); break; + case LoadSettingsMessage: + notification_load_settings(app); + break; } if(message.back_event != NULL) { diff --git a/applications/services/notification/notification_app.h b/applications/services/notification/notification_app.h index c6d68a551..9c1ecddcf 100644 --- a/applications/services/notification/notification_app.h +++ b/applications/services/notification/notification_app.h @@ -2,6 +2,7 @@ #include #include "notification.h" #include "notification_messages.h" +#include "notification_settings_filename.h" #define NOTIFICATION_LED_COUNT 3 #define NOTIFICATION_EVENT_COMPLETE 0x00000001U @@ -10,6 +11,7 @@ typedef enum { NotificationLayerMessage, InternalLayerMessage, SaveSettingsMessage, + LoadSettingsMessage, } NotificationAppMessageType; typedef struct { @@ -33,7 +35,6 @@ typedef struct { #define NOTIFICATION_SETTINGS_VERSION 0x02 #define NOTIFICATION_SETTINGS_MAGIC 0x16 -#define NOTIFICATION_SETTINGS_PATH CFG_PATH("notification.settings") typedef struct { uint8_t version; @@ -48,7 +49,6 @@ typedef struct { struct NotificationApp { FuriMessageQueue* queue; FuriPubSub* event_record; - FuriPubSub* ascii_record; FuriTimer* display_timer; NotificationLedLayer display; @@ -56,6 +56,8 @@ struct NotificationApp { uint8_t display_led_lock; NotificationSettings settings; + + FuriPubSub* ascii_record; }; #ifdef __cplusplus diff --git a/applications/services/notification/notification_settings_filename.h b/applications/services/notification/notification_settings_filename.h new file mode 100644 index 000000000..169bb1472 --- /dev/null +++ b/applications/services/notification/notification_settings_filename.h @@ -0,0 +1,5 @@ +#pragma once + +#define NOTIFICATION_SETTINGS_FILE_NAME ".notification.settings" + +#define NOTIFICATION_SETTINGS_PATH INT_PATH(NOTIFICATION_SETTINGS_FILE_NAME) diff --git a/applications/services/power/application.fam b/applications/services/power/application.fam index 6514e41b3..f973ab2b6 100644 --- a/applications/services/power/application.fam +++ b/applications/services/power/application.fam @@ -14,7 +14,7 @@ App( ], stack_size=1 * 1024, order=110, - sdk_headers=["power_service/power.h", "power_settings.h"], + sdk_headers=["power_service/power.h"], ) App( diff --git a/applications/services/power/power_cli.c b/applications/services/power/power_cli.c index 89cd723ee..0b2a9851b 100644 --- a/applications/services/power/power_cli.c +++ b/applications/services/power/power_cli.c @@ -17,13 +17,15 @@ void power_cli_off(Cli* cli, FuriString* args) { void power_cli_reboot(Cli* cli, FuriString* args) { UNUSED(cli); UNUSED(args); - power_reboot(PowerBootModeNormal); + Power* power = furi_record_open(RECORD_POWER); + power_reboot(power, PowerBootModeNormal); } void power_cli_reboot2dfu(Cli* cli, FuriString* args) { UNUSED(cli); UNUSED(args); - power_reboot(PowerBootModeDfu); + Power* power = furi_record_open(RECORD_POWER); + power_reboot(power, PowerBootModeDfu); } void power_cli_5v(Cli* cli, FuriString* args) { diff --git a/applications/services/power/power_service/power.c b/applications/services/power/power_service/power.c index 74217c354..987bb6861 100644 --- a/applications/services/power/power_service/power.c +++ b/applications/services/power/power_service/power.c @@ -2,19 +2,21 @@ #include #include +#include #include +#include +#include + #define TAG "Power" -#define POWER_OFF_TIMEOUT 90 +#define POWER_OFF_TIMEOUT_S (90U) +#define POWER_POLL_PERIOD_MS (1000UL) -void power_set_battery_icon_enabled(Power* power, bool is_enabled) { - furi_assert(power); +#define POWER_VBUS_LOW_THRESHOLD (4.0f) +#define POWER_HEALTH_LOW_THRESHOLD (70U) - view_port_enabled_set(power->battery_view_port, is_enabled); -} - -void power_draw_battery_callback(Canvas* canvas, void* context) { +static void power_draw_battery_callback(Canvas* canvas, void* context) { furi_assert(context); Power* power = context; BatteryIcon battery_icon = momentum_settings.battery_icon; @@ -237,6 +239,7 @@ void power_draw_battery_callback(Canvas* canvas, void* context) { } canvas_set_bitmap_mode(canvas, false); } + } else { canvas_draw_box(canvas, 8, 3, 8, 2); } @@ -246,12 +249,12 @@ static ViewPort* power_battery_view_port_alloc(Power* power) { ViewPort* battery_view_port = view_port_alloc(); view_port_set_width(battery_view_port, icon_get_width(&I_Battery_25x8)); view_port_draw_callback_set(battery_view_port, power_draw_battery_callback, power); - gui_add_view_port(power->gui, battery_view_port, GuiLayerStatusBarRight); return battery_view_port; } static void power_start_auto_shutdown_timer(Power* power) { - furi_timer_start(power->auto_shutdown_timer, furi_ms_to_ticks(power->shutdown_idle_delay_ms)); + furi_timer_start( + power->auto_shutdown_timer, furi_ms_to_ticks(power->settings.shutdown_idle_delay_ms)); } static void power_stop_auto_shutdown_timer(Power* power) { @@ -271,7 +274,7 @@ static void power_auto_shutdown_callback(const void* value, void* context) { } static void power_auto_shutdown_arm(Power* power) { - if(power->shutdown_idle_delay_ms) { + if(power->settings.shutdown_idle_delay_ms) { if(power->input_events_subscription == NULL) { power->input_events_subscription = furi_pubsub_subscribe( power->input_events_pubsub, power_auto_shutdown_callback, power); @@ -302,14 +305,31 @@ static void power_loader_callback(const void* message, void* context) { const LoaderEvent* event = message; if(event->type == LoaderEventTypeApplicationBeforeLoad) { + power->app_running = true; power_auto_shutdown_inhibit(power); } else if( event->type == LoaderEventTypeApplicationLoadFailed || event->type == LoaderEventTypeApplicationStopped) { + power->app_running = false; power_auto_shutdown_arm(power); } } +static void power_storage_callback(const void* message, void* context) { + furi_assert(context); + Power* power = context; + const StorageEvent* event = message; + + if(event->type == StorageEventTypeCardMount) { + PowerMessage msg = { + .type = PowerMessageTypeReloadSettings, + }; + + furi_check( + furi_message_queue_put(power->message_queue, &msg, FuriWaitForever) == FuriStatusOk); + } +} + static void power_auto_shutdown_timer_callback(void* context) { furi_assert(context); Power* power = context; @@ -317,121 +337,66 @@ static void power_auto_shutdown_timer_callback(void* context) { power_off(power); } -static void power_shutdown_time_changed_callback(const void* event, void* context) { - furi_assert(event); - furi_assert(context); - Power* power = context; - power->shutdown_idle_delay_ms = *(uint32_t*)event; - if(power->shutdown_idle_delay_ms) { +static void power_apply_settings(Power* power) { + if(power->settings.shutdown_idle_delay_ms && !power->app_running) { power_auto_shutdown_arm(power); } else if(power_is_running_auto_shutdown_timer(power)) { power_auto_shutdown_inhibit(power); } } -Power* power_alloc(void) { - Power* power = malloc(sizeof(Power)); +static bool power_update_info(Power* power) { + const PowerInfo info = { + .is_charging = furi_hal_power_is_charging(), + .gauge_is_ok = furi_hal_power_gauge_is_ok(), + .is_shutdown_requested = furi_hal_power_is_shutdown_requested(), + .charge = furi_hal_power_get_pct(), + .health = furi_hal_power_get_bat_health_pct(), + .capacity_remaining = furi_hal_power_get_battery_remaining_capacity(), + .capacity_full = furi_hal_power_get_battery_full_capacity(), + .current_charger = furi_hal_power_get_battery_current(FuriHalPowerICCharger), + .current_gauge = furi_hal_power_get_battery_current(FuriHalPowerICFuelGauge), + .voltage_battery_charge_limit = furi_hal_power_get_battery_charge_voltage_limit(), + .voltage_charger = furi_hal_power_get_battery_voltage(FuriHalPowerICCharger), + .voltage_gauge = furi_hal_power_get_battery_voltage(FuriHalPowerICFuelGauge), + .voltage_vbus = furi_hal_power_get_usb_voltage(), + .temperature_charger = furi_hal_power_get_battery_temperature(FuriHalPowerICCharger), + .temperature_gauge = furi_hal_power_get_battery_temperature(FuriHalPowerICFuelGauge), + }; - // Records - power->notification = furi_record_open(RECORD_NOTIFICATION); - power->gui = furi_record_open(RECORD_GUI); - - // Pubsub - power->event_pubsub = furi_pubsub_alloc(); - power->settings_events = furi_pubsub_alloc(); - power->loader = furi_record_open(RECORD_LOADER); - power->input_events_pubsub = furi_record_open(RECORD_INPUT_EVENTS); - power->input_events_subscription = NULL; - power->ascii_events_pubsub = furi_record_open(RECORD_ASCII_EVENTS); - power->ascii_events_subscription = NULL; - power->app_start_stop_subscription = - furi_pubsub_subscribe(loader_get_pubsub(power->loader), power_loader_callback, power); - power->settings_events_subscription = - furi_pubsub_subscribe(power->settings_events, power_shutdown_time_changed_callback, power); - - // State initialization - power->state = PowerStateNotCharging; - power->battery_low = false; - power->power_off_timeout = POWER_OFF_TIMEOUT; - power->api_mtx = furi_mutex_alloc(FuriMutexTypeNormal); - - // Gui - power->view_dispatcher = view_dispatcher_alloc(); - power->power_off = power_off_alloc(); - view_dispatcher_add_view( - power->view_dispatcher, PowerViewOff, power_off_get_view(power->power_off)); - power->power_unplug_usb = power_unplug_usb_alloc(); - view_dispatcher_add_view( - power->view_dispatcher, - PowerViewUnplugUsb, - power_unplug_usb_get_view(power->power_unplug_usb)); - view_dispatcher_attach_to_gui(power->view_dispatcher, power->gui, ViewDispatcherTypeDesktop); - - // Battery view port - power->battery_view_port = power_battery_view_port_alloc(power); - power_set_battery_icon_enabled(power, momentum_settings.battery_icon != BatteryIconOff); - power->show_low_bat_level_message = true; - - //Auto shutdown timer - power->auto_shutdown_timer = - furi_timer_alloc(power_auto_shutdown_timer_callback, FuriTimerTypeOnce, power); - - return power; + const bool need_refresh = (power->info.charge != info.charge) || + (power->info.is_charging != info.is_charging); + power->info = info; + return need_refresh; } static void power_check_charging_state(Power* power) { + NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); + if(furi_hal_power_is_charging()) { if((power->info.charge == 100) || (furi_hal_power_is_charging_done())) { if(power->state != PowerStateCharged) { - notification_internal_message(power->notification, &sequence_charged); + notification_internal_message(notification, &sequence_charged); power->state = PowerStateCharged; power->event.type = PowerEventTypeFullyCharged; furi_pubsub_publish(power->event_pubsub, &power->event); } - } else { - if(power->state != PowerStateCharging) { - notification_internal_message(power->notification, &sequence_charging); - power->state = PowerStateCharging; - power->event.type = PowerEventTypeStartCharging; - furi_pubsub_publish(power->event_pubsub, &power->event); - } - } - } else { - if(power->state != PowerStateNotCharging) { - notification_internal_message(power->notification, &sequence_not_charging); - power->state = PowerStateNotCharging; - power->event.type = PowerEventTypeStopCharging; + + } else if(power->state != PowerStateCharging) { + notification_internal_message(notification, &sequence_charging); + power->state = PowerStateCharging; + power->event.type = PowerEventTypeStartCharging; furi_pubsub_publish(power->event_pubsub, &power->event); } + + } else if(power->state != PowerStateNotCharging) { + notification_internal_message(notification, &sequence_not_charging); + power->state = PowerStateNotCharging; + power->event.type = PowerEventTypeStopCharging; + furi_pubsub_publish(power->event_pubsub, &power->event); } -} -static bool power_update_info(Power* power) { - PowerInfo info; - - info.is_charging = furi_hal_power_is_charging(); - info.gauge_is_ok = furi_hal_power_gauge_is_ok(); - info.is_shutdown_requested = furi_hal_power_is_shutdown_requested(); - info.charge = furi_hal_power_get_pct(); - info.health = furi_hal_power_get_bat_health_pct(); - info.capacity_remaining = furi_hal_power_get_battery_remaining_capacity(); - info.capacity_full = furi_hal_power_get_battery_full_capacity(); - info.current_charger = furi_hal_power_get_battery_current(FuriHalPowerICCharger); - info.current_gauge = furi_hal_power_get_battery_current(FuriHalPowerICFuelGauge); - info.voltage_battery_charge_limit = furi_hal_power_get_battery_charge_voltage_limit(); - info.voltage_charger = furi_hal_power_get_battery_voltage(FuriHalPowerICCharger); - info.voltage_gauge = furi_hal_power_get_battery_voltage(FuriHalPowerICFuelGauge); - info.voltage_vbus = furi_hal_power_get_usb_voltage(); - info.temperature_charger = furi_hal_power_get_battery_temperature(FuriHalPowerICCharger); - info.temperature_gauge = furi_hal_power_get_battery_temperature(FuriHalPowerICFuelGauge); - - furi_mutex_acquire(power->api_mtx, FuriWaitForever); - bool need_refresh = power->info.charge != info.charge; - need_refresh |= power->info.is_charging != info.is_charging; - power->info = info; - furi_mutex_release(power->api_mtx); - - return need_refresh; + furi_record_close(RECORD_NOTIFICATION); } static void power_check_low_battery(Power* power) { @@ -440,40 +405,41 @@ static void power_check_low_battery(Power* power) { } // Check battery charge and vbus voltage - if((power->info.is_shutdown_requested) && (power->info.voltage_vbus < 4.0f) && - power->show_low_bat_level_message) { + if((power->info.is_shutdown_requested) && + (power->info.voltage_vbus < POWER_VBUS_LOW_THRESHOLD) && power->show_battery_low_warning) { if(!power->battery_low) { - view_dispatcher_send_to_front(power->view_dispatcher); - view_dispatcher_switch_to_view(power->view_dispatcher, PowerViewOff); + view_holder_send_to_front(power->view_holder); + view_holder_set_view(power->view_holder, power_off_get_view(power->view_power_off)); } power->battery_low = true; } else { if(power->battery_low) { - view_dispatcher_switch_to_view(power->view_dispatcher, VIEW_NONE); - power->power_off_timeout = POWER_OFF_TIMEOUT; + // view_dispatcher_switch_to_view(power->view_dispatcher, VIEW_NONE); + view_holder_set_view(power->view_holder, NULL); + power->power_off_timeout = POWER_OFF_TIMEOUT_S; } power->battery_low = false; } // If battery low, update view and switch off power after timeout if(power->battery_low) { - PowerOffResponse response = power_off_get_response(power->power_off); + PowerOffResponse response = power_off_get_response(power->view_power_off); if(response == PowerOffResponseDefault) { if(power->power_off_timeout) { - power_off_set_time_left(power->power_off, power->power_off_timeout--); + power_off_set_time_left(power->view_power_off, power->power_off_timeout--); } else { power_off(power); } } else if(response == PowerOffResponseOk) { power_off(power); } else if(response == PowerOffResponseHide) { - view_dispatcher_switch_to_view(power->view_dispatcher, VIEW_NONE); + view_holder_set_view(power->view_holder, NULL); if(power->power_off_timeout) { - power_off_set_time_left(power->power_off, power->power_off_timeout--); + power_off_set_time_left(power->view_power_off, power->power_off_timeout--); } else { power_off(power); } } else if(response == PowerOffResponseCancel) { - view_dispatcher_switch_to_view(power->view_dispatcher, VIEW_NONE); + view_holder_set_view(power->view_holder, NULL); } } } @@ -490,20 +456,171 @@ static void power_check_battery_level_change(Power* power) { static void power_check_charge_cap(Power* power) { uint32_t cap = momentum_settings.charge_cap; if(power->info.charge >= cap && cap < 100) { - if(!power->info.is_charge_capped) { // Suppress charging if charge reaches custom cap - power->info.is_charge_capped = true; + if(!power->is_charge_capped) { // Suppress charging if charge reaches custom cap + power->is_charge_capped = true; furi_hal_power_suppress_charge_enter(); } } else { - if(power->info.is_charge_capped) { // Start charging again if charge below custom cap - power->info.is_charge_capped = false; + if(power->is_charge_capped) { // Start charging again if charge below custom cap + power->is_charge_capped = false; furi_hal_power_suppress_charge_exit(); } } } -void power_trigger_ui_update(Power* power) { - view_port_update(power->battery_view_port); +static void power_handle_shutdown(Power* power) { + furi_hal_power_off(); + // Notify user if USB is plugged + view_holder_send_to_front(power->view_holder); + view_holder_set_view( + power->view_holder, power_unplug_usb_get_view(power->view_power_unplug_usb)); + furi_delay_ms(100); + furi_halt("Disconnect USB for safe shutdown"); +} + +static void power_handle_reboot(PowerBootMode mode) { + if(mode == PowerBootModeNormal) { + update_operation_disarm(); + } else if(mode == PowerBootModeDfu) { + furi_hal_rtc_set_boot_mode(FuriHalRtcBootModeDfu); + } else if(mode == PowerBootModeUpdateStart) { + furi_hal_rtc_set_boot_mode(FuriHalRtcBootModePreUpdate); + } else { + furi_crash(); + } + + furi_hal_power_reset(); +} + +static bool power_message_callback(FuriEventLoopObject* object, void* context) { + furi_assert(context); + Power* power = context; + + furi_assert(object == power->message_queue); + + PowerMessage msg; + furi_check(furi_message_queue_get(power->message_queue, &msg, 0) == FuriStatusOk); + + switch(msg.type) { + case PowerMessageTypeShutdown: + power_handle_shutdown(power); + break; + case PowerMessageTypeReboot: + power_handle_reboot(msg.boot_mode); + break; + case PowerMessageTypeGetInfo: + *msg.power_info = power->info; + break; + case PowerMessageTypeIsBatteryHealthy: + *msg.bool_param = power->info.health > POWER_HEALTH_LOW_THRESHOLD; + break; + case PowerMessageTypeShowBatteryLowWarning: + power->show_battery_low_warning = *msg.bool_param; + break; + case PowerMessageTypeGetSettings: + furi_assert(msg.lock); + *msg.settings = power->settings; + break; + case PowerMessageTypeSetSettings: + furi_assert(msg.lock); + power->settings = *msg.csettings; + power_apply_settings(power); + power_settings_save(&power->settings); + break; + case PowerMessageTypeReloadSettings: + power_settings_load(&power->settings); + power_apply_settings(power); + break; + default: + furi_crash(); + } + + if(msg.lock) { + api_lock_unlock(msg.lock); + } + + return true; +} + +static void power_tick_callback(void* context) { + furi_assert(context); + Power* power = context; + + // Update data from gauge and charger + const bool need_refresh = power_update_info(power); + // Check low battery level + power_check_low_battery(power); + // Check and notify about charging state + power_check_charging_state(power); + // Check and notify about battery level change + power_check_battery_level_change(power); + // Check charge cap, compare with user setting and (un)suppress charging + power_check_charge_cap(power); + // Update battery view port + view_port_enabled_set( + power->battery_view_port, momentum_settings.battery_icon != BatteryIconOff); + if(need_refresh) { + view_port_update(power->battery_view_port); + } + // Check OTG status and disable it in case of fault + if(furi_hal_power_is_otg_enabled()) { + furi_hal_power_check_otg_status(); + } +} + +static void power_init_settings(Power* power) { + Storage* storage = furi_record_open(RECORD_STORAGE); + furi_pubsub_subscribe(storage_get_pubsub(storage), power_storage_callback, power); + + if(storage_sd_status(storage) != FSE_OK) { + FURI_LOG_D(TAG, "SD Card not ready, skipping settings"); + return; + } + + power_settings_load(&power->settings); + power_apply_settings(power); + furi_record_close(RECORD_STORAGE); +} + +static Power* power_alloc(void) { + Power* power = malloc(sizeof(Power)); + // Pubsub + power->event_pubsub = furi_pubsub_alloc(); + // State initialization + power->power_off_timeout = POWER_OFF_TIMEOUT_S; + power->show_battery_low_warning = true; + // Gui + Gui* gui = furi_record_open(RECORD_GUI); + + // Auto shutdown on idle + Loader* loader = furi_record_open(RECORD_LOADER); + furi_pubsub_subscribe(loader_get_pubsub(loader), power_loader_callback, power); + power->input_events_pubsub = furi_record_open(RECORD_INPUT_EVENTS); + power->ascii_events_pubsub = furi_record_open(RECORD_ASCII_EVENTS); + power->auto_shutdown_timer = + furi_timer_alloc(power_auto_shutdown_timer_callback, FuriTimerTypeOnce, power); + + power->view_holder = view_holder_alloc(); + power->view_power_off = power_off_alloc(); + power->view_power_unplug_usb = power_unplug_usb_alloc(); + + view_holder_attach_to_gui(power->view_holder, gui); + // Battery view port + power->battery_view_port = power_battery_view_port_alloc(power); + gui_add_view_port(gui, power->battery_view_port, GuiLayerStatusBarRight); + // Event loop + power->event_loop = furi_event_loop_alloc(); + power->message_queue = furi_message_queue_alloc(4, sizeof(PowerMessage)); + + furi_event_loop_subscribe_message_queue( + power->event_loop, + power->message_queue, + FuriEventLoopEventIn, + power_message_callback, + power); + furi_event_loop_tick_set(power->event_loop, 1000, power_tick_callback, power); + + return power; } int32_t power_srv(void* p) { @@ -517,44 +634,17 @@ int32_t power_srv(void* p) { } Power* power = power_alloc(); - if(!LOAD_POWER_SETTINGS(&power->shutdown_idle_delay_ms)) { - power->shutdown_idle_delay_ms = 0; - } - power_auto_shutdown_arm(power); power_update_info(power); - power->info.is_charge_capped = false; // default false + furi_record_create(RECORD_POWER, power); - while(1) { - // Update data from gauge and charger - bool need_refresh = power_update_info(power); + // Can't be done in alloc, other things in startup need power service and it would deadlock by waiting for loader + Loader* loader = furi_record_open(RECORD_LOADER); + power->app_running = loader_is_locked(loader); + furi_record_close(RECORD_LOADER); + power_init_settings(power); - // Check low battery level - power_check_low_battery(power); - - // Check and notify about charging state - power_check_charging_state(power); - - // Check and notify about battery level change - power_check_battery_level_change(power); - - // Check charge cap, compare with user setting and suppress/unsuppress charging - power_check_charge_cap(power); - - // Update battery view port - if(need_refresh) { - view_port_update(power->battery_view_port); - } - - // Check OTG status and disable it in case of fault - if(furi_hal_power_is_otg_enabled()) { - furi_hal_power_check_otg_status(); - } - - furi_delay_ms(1000); - } - - furi_crash("That was unexpected"); + furi_event_loop_run(power->event_loop); return 0; } diff --git a/applications/services/power/power_service/power.h b/applications/services/power/power_service/power.h index ecb0566a4..0168a8656 100644 --- a/applications/services/power/power_service/power.h +++ b/applications/services/power/power_service/power.h @@ -1,9 +1,10 @@ #pragma once #include -#include #include +#include + #ifdef __cplusplus extern "C" { #endif @@ -55,8 +56,6 @@ typedef struct { uint8_t charge; uint8_t health; - - bool is_charge_capped; } PowerInfo; /** Power off device @@ -67,7 +66,7 @@ void power_off(Power* power); * * @param mode PowerBootMode */ -void power_reboot(PowerBootMode mode); +void power_reboot(Power* power, PowerBootMode mode); /** Get power info * @@ -84,14 +83,6 @@ void power_get_info(Power* power, PowerInfo* info); */ FuriPubSub* power_get_pubsub(Power* power); -/** Get power settings events pubsub handler - * - * @param power Power instance - * - * @return FuriPubSub instance - */ -FuriPubSub* power_get_settings_events_pubsub(Power* power); - /** Check battery health * * @return true if battery is healthy @@ -105,19 +96,6 @@ bool power_is_battery_healthy(Power* power); */ void power_enable_low_battery_level_notification(Power* power, bool enable); -/** Trigger UI update for changing battery layout - * - * @param power Power instance - */ -void power_trigger_ui_update(Power* power); - -/** Enable or disable battery icon - * - * @param power Power instance - * @param is_enabled Show battery or not - */ -void power_set_battery_icon_enabled(Power* power, bool is_enabled); - #ifdef __cplusplus } #endif diff --git a/applications/services/power/power_service/power_api.c b/applications/services/power/power_service/power_api.c index d2b4c4e5b..9c17747af 100644 --- a/applications/services/power/power_service/power_api.c +++ b/applications/services/power/power_service/power_api.c @@ -1,41 +1,39 @@ #include "power_i.h" -#include -#include -#include - void power_off(Power* power) { furi_check(power); - furi_hal_power_off(); - // Notify user if USB is plugged - view_dispatcher_send_to_front(power->view_dispatcher); - view_dispatcher_switch_to_view(power->view_dispatcher, PowerViewUnplugUsb); - furi_delay_ms(100); - furi_halt("Disconnect USB for safe shutdown"); + PowerMessage msg = { + .type = PowerMessageTypeShutdown, + }; + + furi_check( + furi_message_queue_put(power->message_queue, &msg, FuriWaitForever) == FuriStatusOk); } -void power_reboot(PowerBootMode mode) { - if(mode == PowerBootModeNormal) { - update_operation_disarm(); - } else if(mode == PowerBootModeDfu) { - furi_hal_rtc_set_boot_mode(FuriHalRtcBootModeDfu); - } else if(mode == PowerBootModeUpdateStart) { - furi_hal_rtc_set_boot_mode(FuriHalRtcBootModePreUpdate); - } else { - furi_crash(); - } +void power_reboot(Power* power, PowerBootMode mode) { + PowerMessage msg = { + .type = PowerMessageTypeReboot, + .boot_mode = mode, + }; - furi_hal_power_reset(); + furi_check( + furi_message_queue_put(power->message_queue, &msg, FuriWaitForever) == FuriStatusOk); } void power_get_info(Power* power, PowerInfo* info) { furi_check(power); furi_check(info); - furi_mutex_acquire(power->api_mtx, FuriWaitForever); - memcpy(info, &power->info, sizeof(power->info)); - furi_mutex_release(power->api_mtx); + PowerMessage msg = { + .type = PowerMessageTypeGetInfo, + .power_info = info, + .lock = api_lock_alloc_locked(), + }; + + furi_check( + furi_message_queue_put(power->message_queue, &msg, FuriWaitForever) == FuriStatusOk); + api_lock_wait_unlock_and_free(msg.lock); } FuriPubSub* power_get_pubsub(Power* power) { @@ -43,23 +41,66 @@ FuriPubSub* power_get_pubsub(Power* power) { return power->event_pubsub; } -FuriPubSub* power_get_settings_events_pubsub(Power* power) { - furi_assert(power); - return power->settings_events; -} - bool power_is_battery_healthy(Power* power) { furi_check(power); - bool is_healthy = false; - furi_mutex_acquire(power->api_mtx, FuriWaitForever); - is_healthy = power->info.health > POWER_BATTERY_HEALTHY_LEVEL; - furi_mutex_release(power->api_mtx); - return is_healthy; + + bool ret = false; + + PowerMessage msg = { + .type = PowerMessageTypeIsBatteryHealthy, + .lock = api_lock_alloc_locked(), + .bool_param = &ret, + }; + + furi_check( + furi_message_queue_put(power->message_queue, &msg, FuriWaitForever) == FuriStatusOk); + api_lock_wait_unlock_and_free(msg.lock); + + return ret; } void power_enable_low_battery_level_notification(Power* power, bool enable) { furi_check(power); - furi_mutex_acquire(power->api_mtx, FuriWaitForever); - power->show_low_bat_level_message = enable; - furi_mutex_release(power->api_mtx); + + PowerMessage msg = { + .type = PowerMessageTypeShowBatteryLowWarning, + .bool_param = &enable, + }; + + furi_check( + furi_message_queue_put(power->message_queue, &msg, FuriWaitForever) == FuriStatusOk); +} + +/* + * Private API for the Settings app + */ + +void power_get_settings(Power* power, PowerSettings* settings) { + furi_assert(power); + furi_assert(settings); + + PowerMessage msg = { + .type = PowerMessageTypeGetSettings, + .settings = settings, + .lock = api_lock_alloc_locked(), + }; + + furi_check( + furi_message_queue_put(power->message_queue, &msg, FuriWaitForever) == FuriStatusOk); + api_lock_wait_unlock_and_free(msg.lock); +} + +void power_set_settings(Power* power, const PowerSettings* settings) { + furi_assert(power); + furi_assert(settings); + + PowerMessage msg = { + .type = PowerMessageTypeSetSettings, + .csettings = settings, + .lock = api_lock_alloc_locked(), + }; + + furi_check( + furi_message_queue_put(power->message_queue, &msg, FuriWaitForever) == FuriStatusOk); + api_lock_wait_unlock_and_free(msg.lock); } diff --git a/applications/services/power/power_service/power_i.h b/applications/services/power/power_service/power_i.h index 0c6b2658d..7f4a7ae0c 100644 --- a/applications/services/power/power_service/power_i.h +++ b/applications/services/power/power_service/power_i.h @@ -2,20 +2,16 @@ #include "power.h" -#include -#include #include -#include -#include +#include + +#include +#include -#include #include "views/power_off.h" -#include #include "views/power_unplug_usb.h" -#include - -#define POWER_BATTERY_HEALTHY_LEVEL 70 +#include typedef enum { PowerStateNotCharging, @@ -24,39 +20,60 @@ typedef enum { } PowerState; struct Power { - ViewDispatcher* view_dispatcher; - PowerOff* power_off; - PowerUnplugUsb* power_unplug_usb; + ViewHolder* view_holder; + FuriPubSub* event_pubsub; + FuriEventLoop* event_loop; + FuriMessageQueue* message_queue; ViewPort* battery_view_port; - Gui* gui; - NotificationApp* notification; - FuriPubSub* event_pubsub; - PowerEvent event; + PowerOff* view_power_off; + PowerUnplugUsb* view_power_unplug_usb; + PowerEvent event; PowerState state; PowerInfo info; bool battery_low; - bool show_low_bat_level_message; + bool show_battery_low_warning; uint8_t battery_level; uint8_t power_off_timeout; - FuriMutex* api_mtx; - - FuriPubSub* settings_events; FuriPubSub* input_events_pubsub; - FuriPubSubSubscription* input_events_subscription; FuriPubSub* ascii_events_pubsub; + FuriPubSubSubscription* input_events_subscription; FuriPubSubSubscription* ascii_events_subscription; - FuriPubSubSubscription* app_start_stop_subscription; - FuriPubSubSubscription* settings_events_subscription; - uint32_t shutdown_idle_delay_ms; FuriTimer* auto_shutdown_timer; - Loader* loader; + PowerSettings settings; + bool is_charge_capped; + bool app_running; }; typedef enum { PowerViewOff, PowerViewUnplugUsb, } PowerView; + +typedef enum { + PowerMessageTypeShutdown, + PowerMessageTypeReboot, + PowerMessageTypeGetInfo, + PowerMessageTypeIsBatteryHealthy, + PowerMessageTypeShowBatteryLowWarning, + + PowerMessageTypeGetSettings, + PowerMessageTypeSetSettings, + PowerMessageTypeReloadSettings, +} PowerMessageType; + +typedef struct { + PowerMessageType type; + union { + PowerBootMode boot_mode; + PowerInfo* power_info; + bool* bool_param; + + PowerSettings* settings; + const PowerSettings* csettings; + }; + FuriApiLock lock; +} PowerMessage; diff --git a/applications/services/power/power_service/power_settings_api_i.h b/applications/services/power/power_service/power_settings_api_i.h new file mode 100644 index 000000000..ed6c2c34b --- /dev/null +++ b/applications/services/power/power_service/power_settings_api_i.h @@ -0,0 +1,8 @@ +#pragma once + +#include "power.h" +#include "../power_settings.h" + +void power_get_settings(Power* power, PowerSettings* settings); + +void power_set_settings(Power* power, const PowerSettings* settings); diff --git a/applications/services/power/power_settings.c b/applications/services/power/power_settings.c index b98c382c0..926f48e78 100644 --- a/applications/services/power/power_settings.c +++ b/applications/services/power/power_settings.c @@ -1,11 +1,42 @@ #include "power_settings.h" +#include "power_settings_filename.h" -bool SAVE_POWER_SETTINGS(uint32_t* x) { - return saved_struct_save( - POWER_SETTINGS_PATH, x, sizeof(uint32_t), POWER_SETTINGS_MAGIC, POWER_SETTINGS_VER); +#include +#include + +#define TAG "PowerSettings" + +#define POWER_SETTINGS_VER (1) +#define POWER_SETTINGS_MAGIC (0x21) + +void power_settings_load(PowerSettings* settings) { + furi_assert(settings); + + const bool success = saved_struct_load( + POWER_SETTINGS_PATH, + settings, + sizeof(PowerSettings), + POWER_SETTINGS_MAGIC, + POWER_SETTINGS_VER); + + if(!success) { + FURI_LOG_W(TAG, "Failed to load file, using defaults"); + memset(settings, 0, sizeof(PowerSettings)); + // power_settings_save(settings); + } } -bool LOAD_POWER_SETTINGS(uint32_t* x) { - return saved_struct_load( - POWER_SETTINGS_PATH, x, sizeof(uint32_t), POWER_SETTINGS_MAGIC, POWER_SETTINGS_VER); +void power_settings_save(const PowerSettings* settings) { + furi_assert(settings); + + const bool success = saved_struct_save( + POWER_SETTINGS_PATH, + settings, + sizeof(PowerSettings), + POWER_SETTINGS_MAGIC, + POWER_SETTINGS_VER); + + if(!success) { + FURI_LOG_E(TAG, "Failed to save file"); + } } diff --git a/applications/services/power/power_settings.h b/applications/services/power/power_settings.h index df16f72af..4f94b9b69 100644 --- a/applications/services/power/power_settings.h +++ b/applications/services/power/power_settings.h @@ -1,19 +1,10 @@ -#include -#include +#pragma once -#define POWER_SETTINGS_VER (1) +#include -#define POWER_SETTINGS_PATH CFG_PATH("power.settings") -#define POWER_SETTINGS_MAGIC (0x21) +typedef struct { + uint32_t shutdown_idle_delay_ms; +} PowerSettings; -#ifdef __cplusplus -extern "C" { -#endif - -bool SAVE_POWER_SETTINGS(uint32_t* x); - -bool LOAD_POWER_SETTINGS(uint32_t* x); - -#ifdef __cplusplus -} -#endif +void power_settings_load(PowerSettings* settings); +void power_settings_save(const PowerSettings* settings); diff --git a/applications/services/power/power_settings_filename.h b/applications/services/power/power_settings_filename.h new file mode 100644 index 000000000..6aa7c65c1 --- /dev/null +++ b/applications/services/power/power_settings_filename.h @@ -0,0 +1,3 @@ +#pragma once + +#define POWER_SETTINGS_PATH INT_PATH(".power.settings") diff --git a/applications/services/region/application.fam b/applications/services/region/application.fam new file mode 100644 index 000000000..a4cdc94ea --- /dev/null +++ b/applications/services/region/application.fam @@ -0,0 +1,10 @@ +App( + appid="region", + name="RegionSrv", + apptype=FlipperAppType.STARTUP, + targets=["f7"], + entry_point="region_on_system_start", + cdefines=["SRV_REGION"], + requires=["storage"], + order=170, +) diff --git a/applications/services/region/region.c b/applications/services/region/region.c new file mode 100644 index 000000000..dffcc6b2d --- /dev/null +++ b/applications/services/region/region.c @@ -0,0 +1,147 @@ +#include + +#include +#include + +#include +#include + +#define TAG "RegionSrv" + +#define SUBGHZ_REGION_FILENAME INT_PATH(".region_data") + +static bool region_istream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) { + File* file = istream->state; + size_t ret = storage_file_read(file, buf, count); + return count == ret; +} + +static bool region_istream_decode_band(pb_istream_t* stream, const pb_field_t* field, void** arg) { + UNUSED(field); + + FuriHalRegion* region = *arg; + + PB_Region_Band band = {0}; + if(!pb_decode(stream, PB_Region_Band_fields, &band)) { + FURI_LOG_E(TAG, "PB Region band decode error: %s", PB_GET_ERROR(stream)); + return false; + } + + region->bands_count += 1; + region = realloc( //-V701 + region, + sizeof(FuriHalRegion) + sizeof(FuriHalRegionBand) * region->bands_count); + size_t pos = region->bands_count - 1; + region->bands[pos].start = band.start; + region->bands[pos].end = band.end; + region->bands[pos].power_limit = band.power_limit; + region->bands[pos].duty_cycle = band.duty_cycle; + *arg = region; + + FURI_LOG_I( + TAG, + "Add allowed band: start %luHz, stop %luHz, power_limit %ddBm, duty_cycle %u%%", + band.start, + band.end, + band.power_limit, + band.duty_cycle); + return true; +} + +static int32_t region_load_file(void* context) { + UNUSED(context); + + Storage* storage = furi_record_open(RECORD_STORAGE); + File* file = storage_file_alloc(storage); + + PB_Region pb_region = {0}; + pb_region.bands.funcs.decode = region_istream_decode_band; + + do { + FileInfo fileinfo = {0}; + + if(storage_common_stat(storage, SUBGHZ_REGION_FILENAME, &fileinfo) != FSE_OK || + fileinfo.size == 0) { + FURI_LOG_W(TAG, "Region file missing or empty"); + break; + + } else if(!storage_file_open(file, SUBGHZ_REGION_FILENAME, FSAM_READ, FSOM_OPEN_EXISTING)) { + FURI_LOG_E(TAG, "Failed to open region file"); + break; + } + + pb_istream_t istream = { + .callback = region_istream_read, + .state = file, + .errmsg = NULL, + .bytes_left = fileinfo.size, + }; + + pb_region.bands.arg = malloc(sizeof(FuriHalRegion)); + + if(!pb_decode(&istream, PB_Region_fields, &pb_region)) { + FURI_LOG_E(TAG, "Failed to decode region file"); + free(pb_region.bands.arg); + break; + } + + FuriHalRegion* region = pb_region.bands.arg; + + memcpy( + region->country_code, + pb_region.country_code->bytes, + MIN(pb_region.country_code->size, sizeof(region->country_code) - 1)); + + furi_hal_region_set(region); + + FURI_LOG_I(TAG, "Dynamic region set: %s", region->country_code); + } while(0); + + pb_release(PB_Region_fields, &pb_region); + storage_file_free(file); + furi_record_close(RECORD_STORAGE); + + return 0; +} + +static void region_loader_pending_callback(void* context, uint32_t arg) { + UNUSED(arg); + + FuriThread* loader = context; + furi_thread_join(loader); + furi_thread_free(loader); +} + +static void region_loader_state_callback(FuriThreadState state, void* context) { + UNUSED(context); + + if(state == FuriThreadStateStopped) { + furi_timer_pending_callback(region_loader_pending_callback, furi_thread_get_current(), 0); + } +} + +static void region_storage_callback(const void* message, void* context) { + UNUSED(context); + const StorageEvent* event = message; + + if(event->type == StorageEventTypeCardMount) { + FuriThread* loader = furi_thread_alloc_ex(NULL, 2048, region_load_file, NULL); + furi_thread_set_state_callback(loader, region_loader_state_callback); + furi_thread_start(loader); + } +} + +int32_t region_on_system_start(void* p) { + UNUSED(p); + + Storage* storage = furi_record_open(RECORD_STORAGE); + furi_pubsub_subscribe(storage_get_pubsub(storage), region_storage_callback, NULL); + + if(storage_sd_status(storage) != FSE_OK) { + FURI_LOG_D(TAG, "SD Card not ready, skipping dynamic region"); + return 0; + } + + region_load_file(NULL); + return 0; +} diff --git a/applications/services/rpc/rpc.c b/applications/services/rpc/rpc.c index cbecf3dca..821d8f53b 100644 --- a/applications/services/rpc/rpc.c +++ b/applications/services/rpc/rpc.c @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include diff --git a/applications/services/rpc/rpc_system.c b/applications/services/rpc/rpc_system.c index 0b9fd33f9..1cc0f90eb 100644 --- a/applications/services/rpc/rpc_system.c +++ b/applications/services/rpc/rpc_system.c @@ -54,18 +54,21 @@ static void rpc_system_system_reboot_process(const PB_Main* request, void* conte RpcSession* session = (RpcSession*)context; furi_assert(session); + Power* power = furi_record_open(RECORD_POWER); const int mode = request->content.system_reboot_request.mode; if(mode == PB_System_RebootRequest_RebootMode_OS) { - power_reboot(PowerBootModeNormal); + power_reboot(power, PowerBootModeNormal); } else if(mode == PB_System_RebootRequest_RebootMode_DFU) { - power_reboot(PowerBootModeDfu); + power_reboot(power, PowerBootModeDfu); } else if(mode == PB_System_RebootRequest_RebootMode_UPDATE) { - power_reboot(PowerBootModeUpdateStart); + power_reboot(power, PowerBootModeUpdateStart); } else { rpc_send_and_release_empty( session, request->command_id, PB_CommandStatus_ERROR_INVALID_PARAMETERS); } + + furi_record_close(RECORD_POWER); } static void rpc_system_system_device_info_callback( @@ -181,9 +184,9 @@ static void rpc_system_system_factory_reset_process(const PB_Main* request, void furi_hal_rtc_reset_registers(); furi_hal_rtc_set_flag(FuriHalRtcFlagStorageFormatInternal); - power_reboot(PowerBootModeNormal); - (void)session; + Power* power = furi_record_open(RECORD_POWER); + power_reboot(power, PowerBootModeNormal); } static void diff --git a/applications/services/storage/storage.c b/applications/services/storage/storage.c index 6bb5ac645..c8e803817 100644 --- a/applications/services/storage/storage.c +++ b/applications/services/storage/storage.c @@ -3,7 +3,6 @@ #include "storage_message.h" #include "storage_processing.h" #include "storage/storage_glue.h" -#include "storages/storage_int.h" #include "storages/storage_ext.h" #include @@ -42,9 +41,6 @@ Storage* storage_app_alloc(void) { storage_data_timestamp(&app->storage[i]); } -#ifndef FURI_RAM_EXEC - storage_int_init(&app->storage[ST_INT]); -#endif storage_ext_init(&app->storage[ST_EXT]); #ifndef FURI_RAM_EXEC storage_mnt_init(&app->storage[ST_MNT]); @@ -60,6 +56,25 @@ Storage* storage_app_alloc(void) { return app; } +#ifndef FURI_RAM_EXEC +#include +#include + +static int32_t sd_mount_callback(void* context) { + Storage* app = context; + StorageEvent event = {.type = StorageEventTypeCardMount}; + + // Needs to happen before other services load their settings + flipper_mount_callback(&event, NULL); + + // Everything else + furi_pubsub_publish(app->pubsub, &event); + + furi_record_close(RECORD_STORAGE); + return 0; +} +#endif + void storage_tick(Storage* app) { for(uint8_t i = 0; i < STORAGE_COUNT; i++) { StorageApi api = app->storage[i].api; @@ -90,8 +105,14 @@ void storage_tick(Storage* app) { if(app->storage[ST_EXT].status == StorageStatusOK) { FURI_LOG_I(TAG, "SD card mount"); +#ifndef FURI_RAM_EXEC + // Can't use pubsub for migration and can't lockup storage thread, + // see more explanation in flipper_mount_callback() + run_parallel(sd_mount_callback, app, 3 * 1024); +#else StorageEvent event = {.type = StorageEventTypeCardMount}; furi_pubsub_publish(app->pubsub, &event); +#endif } else { FURI_LOG_I(TAG, "SD card mount error"); StorageEvent event = {.type = StorageEventTypeCardMountError}; diff --git a/applications/services/storage/storage.h b/applications/services/storage/storage.h index 633fbc0ff..4af3458d8 100644 --- a/applications/services/storage/storage.h +++ b/applications/services/storage/storage.h @@ -14,18 +14,17 @@ extern "C" { #define STORAGE_INT_PATH_PREFIX "/int" #define STORAGE_EXT_PATH_PREFIX "/ext" -#define STORAGE_MNT_PATH_PREFIX "/mnt" #define STORAGE_ANY_PATH_PREFIX "/any" +#define STORAGE_MNT_PATH_PREFIX "/mnt" #define STORAGE_APP_DATA_PATH_PREFIX "/data" #define STORAGE_APP_ASSETS_PATH_PREFIX "/assets" -#define STORAGE_CFG_PATH_PREFIX STORAGE_EXT_PATH_PREFIX "/.config" #define INT_PATH(path) STORAGE_INT_PATH_PREFIX "/" path #define EXT_PATH(path) STORAGE_EXT_PATH_PREFIX "/" path #define ANY_PATH(path) STORAGE_ANY_PATH_PREFIX "/" path +#define MNT_PATH(path) STORAGE_MNT_PATH_PREFIX "/" path #define APP_DATA_PATH(path) STORAGE_APP_DATA_PATH_PREFIX "/" path #define APP_ASSETS_PATH(path) STORAGE_APP_ASSETS_PATH_PREFIX "/" path -#define CFG_PATH(path) STORAGE_CFG_PATH_PREFIX "/" path #define RECORD_STORAGE "storage" @@ -534,7 +533,7 @@ FS_Error storage_sd_status(Storage* storage); /******************* Internal LFS Functions *******************/ -typedef void (*Storage_name_converter)(FuriString*); +typedef void (*StorageNameConverter)(FuriString*); /** * @brief Back up the internal storage contents to a *.tar archive. @@ -554,7 +553,7 @@ FS_Error storage_int_backup(Storage* storage, const char* dstname); * @return FSE_OK if the storage was successfully restored, any other error code on failure. */ FS_Error - storage_int_restore(Storage* storage, const char* dstname, Storage_name_converter converter); + storage_int_restore(Storage* storage, const char* dstname, StorageNameConverter converter); /******************* FatFs Virtual Mount Functions *******************/ diff --git a/applications/services/storage/storage_cli.c b/applications/services/storage/storage_cli.c index 0da8adf24..73300ef84 100644 --- a/applications/services/storage/storage_cli.c +++ b/applications/services/storage/storage_cli.c @@ -33,7 +33,7 @@ static void storage_cli_info(Cli* cli, FuriString* path, FuriString* args) { storage_cli_print_error(error); } else { printf( - "Label: %s\r\nType: LittleFS\r\n%luKiB total\r\n%luKiB free\r\n", + "Label: %s\r\nType: Virtual\r\n%luKiB total\r\n%luKiB free\r\n", furi_hal_version_get_name_ptr() ? furi_hal_version_get_name_ptr() : "Unknown", (uint32_t)(total_space / 1024), (uint32_t)(free_space / 1024)); @@ -701,9 +701,12 @@ static void storage_cli_factory_reset(Cli* cli, FuriString* args, void* context) char c = cli_getc(cli); if(c == 'y' || c == 'Y') { printf("Data will be wiped after reboot.\r\n"); + furi_hal_rtc_reset_registers(); furi_hal_rtc_set_flag(FuriHalRtcFlagStorageFormatInternal); - power_reboot(PowerBootModeNormal); + + Power* power = furi_record_open(RECORD_POWER); + power_reboot(power, PowerBootModeNormal); } else { printf("Safe choice.\r\n"); } diff --git a/applications/services/storage/storage_internal_api.c b/applications/services/storage/storage_internal_api.c index 4cbce7546..defab966c 100644 --- a/applications/services/storage/storage_internal_api.c +++ b/applications/services/storage/storage_internal_api.c @@ -14,7 +14,7 @@ FS_Error storage_int_backup(Storage* storage, const char* dstname) { } FS_Error - storage_int_restore(Storage* storage, const char* srcname, Storage_name_converter converter) { + storage_int_restore(Storage* storage, const char* srcname, StorageNameConverter converter) { furi_check(storage); TarArchive* archive = tar_archive_alloc(storage); diff --git a/applications/services/storage/storage_internal_dirname_i.h b/applications/services/storage/storage_internal_dirname_i.h new file mode 100644 index 000000000..889bdc497 --- /dev/null +++ b/applications/services/storage/storage_internal_dirname_i.h @@ -0,0 +1,3 @@ +#pragma once + +#define STORAGE_INTERNAL_DIR_NAME ".int" diff --git a/applications/services/storage/storage_processing.c b/applications/services/storage/storage_processing.c index 70b20e1fb..b60eeda42 100644 --- a/applications/services/storage/storage_processing.c +++ b/applications/services/storage/storage_processing.c @@ -1,7 +1,11 @@ -#include "storage_processing.h" #include #include +#include "storage_processing.h" +#include "storage_internal_dirname_i.h" + +#define TAG "Storage" + #define STORAGE_PATH_PREFIX_LEN 4u _Static_assert( sizeof(STORAGE_ANY_PATH_PREFIX) == STORAGE_PATH_PREFIX_LEN + 1, @@ -62,33 +66,25 @@ static StorageType storage_get_type_by_path(FuriString* path) { return type; } -static void storage_path_change_to_real_storage(FuriString* path, StorageType real_storage) { - if(furi_string_search(path, STORAGE_ANY_PATH_PREFIX) == 0) { - switch(real_storage) { - case ST_EXT: - furi_string_replace_at( - path, 0, strlen(STORAGE_EXT_PATH_PREFIX), STORAGE_EXT_PATH_PREFIX); - break; - case ST_INT: - furi_string_replace_at( - path, 0, strlen(STORAGE_INT_PATH_PREFIX), STORAGE_INT_PATH_PREFIX); - break; - default: - break; - } - } -} FS_Error storage_get_data(Storage* app, FuriString* path, StorageData** storage) { StorageType type = storage_get_type_by_path(path); if(storage_type_is_valid(type)) { + // Any storage phase-out: redirect "/any" to "/ext" if(type == ST_ANY) { - type = ST_INT; - if(storage_data_status(&app->storage[ST_EXT]) == StorageStatusOK) { - type = ST_EXT; - } - storage_path_change_to_real_storage(path, type); + FURI_LOG_W( + TAG, + STORAGE_ANY_PATH_PREFIX " is deprecated, use " STORAGE_EXT_PATH_PREFIX " instead"); + furi_string_replace_at( + path, 0, strlen(STORAGE_EXT_PATH_PREFIX), STORAGE_EXT_PATH_PREFIX); + type = ST_EXT; + } + + furi_assert(type == ST_EXT || type == ST_MNT); + + if(storage_data_status(&app->storage[type]) != StorageStatusOK) { + return FSE_NOT_READY; } *storage = &app->storage[type]; @@ -607,13 +603,16 @@ void storage_process_alias( furi_string_get_cstr(apps_assets_path_with_appsid)); furi_string_free(apps_assets_path_with_appsid); - } else if(furi_string_start_with(path, STORAGE_CFG_PATH_PREFIX)) { - // Create config folder if it doesn't exist - FuriString* config_path = furi_string_alloc_set(STORAGE_CFG_PATH_PREFIX); - if(create_folders && storage_process_common_stat(app, config_path, NULL) != FSE_OK) { - storage_process_common_mkdir(app, config_path); + + } else if(furi_string_start_with(path, STORAGE_INT_PATH_PREFIX)) { + furi_string_replace_at( + path, 0, strlen(STORAGE_INT_PATH_PREFIX), EXT_PATH(STORAGE_INTERNAL_DIR_NAME)); + + FuriString* int_on_ext_path = furi_string_alloc_set(EXT_PATH(STORAGE_INTERNAL_DIR_NAME)); + if(storage_process_common_stat(app, int_on_ext_path, NULL) != FSE_OK) { + storage_process_common_mkdir(app, int_on_ext_path); } - furi_string_free(config_path); + furi_string_free(int_on_ext_path); } } diff --git a/applications/services/storage/storages/storage_ext.c b/applications/services/storage/storages/storage_ext.c index b6597f64e..276d057ae 100644 --- a/applications/services/storage/storages/storage_ext.c +++ b/applications/services/storage/storages/storage_ext.c @@ -1,11 +1,14 @@ -#include "fatfs.h" -#include "../filesystem_api_internal.h" -#include "storage_ext.h" +#include #include -#include "sd_notify.h" #include #include +#include "sd_notify.h" +#include "storage_ext.h" + +#include "../filesystem_api_internal.h" +#include "../storage_internal_dirname_i.h" + typedef FIL SDFile; typedef DIR SDDir; typedef FILINFO SDFileInfo; @@ -94,6 +97,64 @@ static bool sd_mount_card_internal(StorageData* storage, bool notify) { return result; } +static bool sd_remove_recursive(const char* path) { + SDDir* current_dir = malloc(sizeof(DIR)); + SDFileInfo* file_info = malloc(sizeof(FILINFO)); + FuriString* current_path = furi_string_alloc_set(path); + + bool go_deeper = false; + SDError status; + + while(true) { + status = f_opendir(current_dir, furi_string_get_cstr(current_path)); + if(status != FR_OK) break; + + while(true) { + status = f_readdir(current_dir, file_info); + if(status != FR_OK || !strlen(file_info->fname)) break; + + if(file_info->fattrib & AM_DIR) { + furi_string_cat_printf(current_path, "/%s", file_info->fname); + go_deeper = true; + break; + + } else { + FuriString* file_path = furi_string_alloc_printf( + "%s/%s", furi_string_get_cstr(current_path), file_info->fname); + status = f_unlink(furi_string_get_cstr(file_path)); + furi_string_free(file_path); + + if(status != FR_OK) break; + } + } + + status = f_closedir(current_dir); + if(status != FR_OK) break; + + if(go_deeper) { + go_deeper = false; + continue; + } + + status = f_unlink(furi_string_get_cstr(current_path)); + if(status != FR_OK) break; + + if(!furi_string_equal(current_path, path)) { + size_t last_char_pos = furi_string_search_rchar(current_path, '/'); + furi_assert(last_char_pos != FURI_STRING_FAILURE); + furi_string_left(current_path, last_char_pos); + } else { + break; + } + } + + free(current_dir); + free(file_info); + furi_string_free(current_path); + + return status == FR_OK; +} + FS_Error sd_unmount_card(StorageData* storage) { SDData* sd_data = storage->data; SDError error; @@ -113,21 +174,32 @@ FS_Error sd_mount_card(StorageData* storage, bool notify) { if(storage->status != StorageStatusOK) { FURI_LOG_E(TAG, "sd init error: %s", storage_data_status_text(storage)); - if(notify) { - NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); - sd_notify_error(notification); - furi_record_close(RECORD_NOTIFICATION); - } error = FSE_INTERNAL; + } else { FURI_LOG_I(TAG, "card mounted"); - if(notify) { - NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); - sd_notify_success(notification); - furi_record_close(RECORD_NOTIFICATION); - } +#ifndef FURI_RAM_EXEC + if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagStorageFormatInternal)) { + FURI_LOG_I(TAG, "deleting internal storage directory"); + error = sd_remove_recursive(STORAGE_INTERNAL_DIR_NAME) ? FSE_OK : FSE_INTERNAL; + } else { + error = FSE_OK; + } +#else + UNUSED(sd_remove_recursive); error = FSE_OK; +#endif + } + + if(notify) { + NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); + if(error != FSE_OK) { + sd_notify_error(notification); + } else { + sd_notify_success(notification); + } + furi_record_close(RECORD_NOTIFICATION); } return error; @@ -714,6 +786,10 @@ void storage_ext_init(StorageData* storage) { // do not notify on first launch, notifications app is waiting for our thread to read settings storage_ext_tick_internal(storage, false); +#ifndef FURI_RAM_EXEC + // always reset the flag to prevent accidental wipe on SD card insertion + furi_hal_rtc_reset_flag(FuriHalRtcFlagStorageFormatInternal); +#endif } #include "fatfs/ff_gen_drv.h" diff --git a/applications/services/storage/storages/storage_int.c b/applications/services/storage/storages/storage_int.c deleted file mode 100644 index d9e1a90cf..000000000 --- a/applications/services/storage/storages/storage_int.c +++ /dev/null @@ -1,761 +0,0 @@ -#include "storage_int.h" -#include -#include -#include - -#define TAG "StorageInt" - -#define STORAGE_PATH STORAGE_INT_PATH_PREFIX -#define LFS_CLEAN_FINGERPRINT 0 - -/* When less than LFS_RESERVED_PAGES_COUNT are left free, creation & - * modification of non-dot files is restricted */ -#define LFS_RESERVED_PAGES_COUNT 3 - -typedef struct { - const size_t start_address; - const size_t start_page; - struct lfs_config config; - lfs_t lfs; -} LFSData; - -typedef struct { - void* data; - bool open; -} LFSHandle; - -static LFSHandle* lfs_handle_alloc_file(void) { - LFSHandle* handle = malloc(sizeof(LFSHandle)); - handle->data = malloc(sizeof(lfs_file_t)); - return handle; -} - -static LFSHandle* lfs_handle_alloc_dir(void) { - LFSHandle* handle = malloc(sizeof(LFSHandle)); - handle->data = malloc(sizeof(lfs_dir_t)); - return handle; -} - -/* INTERNALS */ - -static lfs_dir_t* lfs_handle_get_dir(LFSHandle* handle) { - return handle->data; -} - -static lfs_file_t* lfs_handle_get_file(LFSHandle* handle) { - return handle->data; -} - -static void lfs_handle_free(LFSHandle* handle) { - free(handle->data); - free(handle); -} - -static void lfs_handle_set_open(LFSHandle* handle) { - handle->open = true; -} - -static bool lfs_handle_is_open(LFSHandle* handle) { - return handle->open; -} - -static lfs_t* lfs_get_from_storage(StorageData* storage) { - return &((LFSData*)storage->data)->lfs; -} - -static LFSData* lfs_data_get_from_storage(StorageData* storage) { - return (LFSData*)storage->data; -} - -static int storage_int_device_read( - const struct lfs_config* c, - lfs_block_t block, - lfs_off_t off, - void* buffer, - lfs_size_t size) { - LFSData* lfs_data = c->context; - size_t address = lfs_data->start_address + block * c->block_size + off; - - FURI_LOG_T( - TAG, - "Device read: block %lu, off %lu, buffer: %p, size %lu, translated address: %p", - block, - off, - buffer, - size, - (void*)address); - - memcpy(buffer, (void*)address, size); - - return 0; -} - -static int storage_int_device_prog( - const struct lfs_config* c, - lfs_block_t block, - lfs_off_t off, - const void* buffer, - lfs_size_t size) { - LFSData* lfs_data = c->context; - size_t address = lfs_data->start_address + block * c->block_size + off; - - FURI_LOG_T( - TAG, - "Device prog: block %lu, off %lu, buffer: %p, size %lu, translated address: %p", - block, - off, - buffer, - size, - (void*)address); - - int ret = 0; - while(size > 0) { - furi_hal_flash_write_dword(address, *(uint64_t*)buffer); - address += c->prog_size; - buffer += c->prog_size; - size -= c->prog_size; - } - - return ret; -} - -static int storage_int_device_erase(const struct lfs_config* c, lfs_block_t block) { - LFSData* lfs_data = c->context; - size_t page = lfs_data->start_page + block; - - FURI_LOG_D(TAG, "Device erase: page %lu, translated page: %zx", block, page); - - furi_hal_flash_erase(page); - return 0; -} - -static int storage_int_device_sync(const struct lfs_config* c) { - UNUSED(c); - FURI_LOG_D(TAG, "Device sync: skipping"); - return 0; -} - -static LFSData* storage_int_lfs_data_alloc(void) { - LFSData* lfs_data = malloc(sizeof(LFSData)); - - // Internal storage start address - *(size_t*)(&lfs_data->start_address) = furi_hal_flash_get_free_page_start_address(); - *(size_t*)(&lfs_data->start_page) = - (lfs_data->start_address - furi_hal_flash_get_base()) / furi_hal_flash_get_page_size(); - - // LFS configuration - // Glue and context - lfs_data->config.context = lfs_data; - lfs_data->config.read = storage_int_device_read; - lfs_data->config.prog = storage_int_device_prog; - lfs_data->config.erase = storage_int_device_erase; - lfs_data->config.sync = storage_int_device_sync; - - // Block device description - lfs_data->config.read_size = furi_hal_flash_get_read_block_size(); - lfs_data->config.prog_size = furi_hal_flash_get_write_block_size(); - lfs_data->config.block_size = furi_hal_flash_get_page_size(); - lfs_data->config.block_count = furi_hal_flash_get_free_page_count(); - lfs_data->config.block_cycles = furi_hal_flash_get_cycles_count(); - lfs_data->config.cache_size = 16; - lfs_data->config.lookahead_size = 16; - - return lfs_data; -} - -// Returns true if fingerprint was invalid and LFS reformatting is needed -static bool storage_int_check_and_set_fingerprint(LFSData* lfs_data) { - bool value = false; - - uint32_t os_fingerprint = 0; - os_fingerprint |= ((lfs_data->start_page & 0xFF) << 0); - os_fingerprint |= ((lfs_data->config.block_count & 0xFF) << 8); - os_fingerprint |= ((LFS_DISK_VERSION_MAJOR & 0xFFFF) << 16); - - uint32_t rtc_fingerprint = furi_hal_rtc_get_register(FuriHalRtcRegisterLfsFingerprint); - if(rtc_fingerprint == LFS_CLEAN_FINGERPRINT) { - FURI_LOG_I(TAG, "Storing LFS fingerprint in RTC"); - furi_hal_rtc_set_register(FuriHalRtcRegisterLfsFingerprint, os_fingerprint); - } else if(rtc_fingerprint != os_fingerprint) { - FURI_LOG_E(TAG, "LFS fingerprint mismatch"); - furi_hal_rtc_set_register(FuriHalRtcRegisterLfsFingerprint, os_fingerprint); - value = true; - } - - return value; -} - -static void storage_int_lfs_mount(LFSData* lfs_data, StorageData* storage) { - int err; - lfs_t* lfs = &lfs_data->lfs; - - bool was_fingerprint_outdated = storage_int_check_and_set_fingerprint(lfs_data); - bool need_format = furi_hal_rtc_is_flag_set(FuriHalRtcFlagStorageFormatInternal) || - was_fingerprint_outdated; - - if(need_format) { - // Format storage - err = lfs_format(lfs, &lfs_data->config); - if(err == 0) { - FURI_LOG_I(TAG, "Factory reset: Format successful, trying to mount"); - furi_hal_rtc_reset_flag(FuriHalRtcFlagStorageFormatInternal); - err = lfs_mount(lfs, &lfs_data->config); - if(err == 0) { - FURI_LOG_I(TAG, "Factory reset: Mounted"); - storage->status = StorageStatusOK; - } else { - FURI_LOG_E(TAG, "Factory reset: Mount after format failed"); - storage->status = StorageStatusNotMounted; - } - } else { - FURI_LOG_E(TAG, "Factory reset: Format failed"); - storage->status = StorageStatusNoFS; - } - } else { - // Normal - err = lfs_mount(lfs, &lfs_data->config); - if(err == 0) { - FURI_LOG_I(TAG, "Mounted"); - storage->status = StorageStatusOK; - } else { - FURI_LOG_E(TAG, "Mount failed, formatting"); - err = lfs_format(lfs, &lfs_data->config); - if(err == 0) { - FURI_LOG_I(TAG, "Format successful, trying to mount"); - err = lfs_mount(lfs, &lfs_data->config); - if(err == 0) { - FURI_LOG_I(TAG, "Mounted"); - storage->status = StorageStatusOK; - } else { - FURI_LOG_E(TAG, "Mount after format failed"); - storage->status = StorageStatusNotMounted; - } - } else { - FURI_LOG_E(TAG, "Format failed"); - storage->status = StorageStatusNoFS; - } - } - } -} - -/****************** Common Functions ******************/ - -static FS_Error storage_int_parse_error(int error) { - FS_Error result; - - if(error >= LFS_ERR_OK) { - result = FSE_OK; - } else { - switch(error) { - case LFS_ERR_NOENT: - result = FSE_NOT_EXIST; - break; - case LFS_ERR_EXIST: - result = FSE_EXIST; - break; - case LFS_ERR_NOTEMPTY: - result = FSE_DENIED; - break; - case LFS_ERR_INVAL: - case LFS_ERR_NOATTR: - result = FSE_INVALID_PARAMETER; - break; - case LFS_ERR_BADF: - case LFS_ERR_ISDIR: - case LFS_ERR_NOTDIR: - case LFS_ERR_NAMETOOLONG: - result = FSE_INVALID_NAME; - break; - case LFS_ERR_IO: - case LFS_ERR_FBIG: - case LFS_ERR_NOSPC: - case LFS_ERR_NOMEM: - case LFS_ERR_CORRUPT: - default: - result = FSE_INTERNAL; - } - } - - return result; -} - -/* Returns false if less than reserved space is left free */ -static bool storage_int_check_for_free_space(StorageData* storage) { - LFSData* lfs_data = lfs_data_get_from_storage(storage); - - lfs_ssize_t result = lfs_fs_size(lfs_get_from_storage(storage)); - if(result >= 0) { - lfs_size_t free_space = - (lfs_data->config.block_count - result) * lfs_data->config.block_size; - - return free_space > LFS_RESERVED_PAGES_COUNT * furi_hal_flash_get_page_size(); - } - - return false; -} -/******************* File Functions *******************/ - -static bool storage_int_file_open( - void* ctx, - File* file, - const char* path, - FS_AccessMode access_mode, - FS_OpenMode open_mode) { - StorageData* storage = ctx; - lfs_t* lfs = lfs_get_from_storage(storage); - - bool enough_free_space = storage_int_check_for_free_space(storage); - - int flags = 0; - - if(access_mode & FSAM_READ) flags |= LFS_O_RDONLY; - if(access_mode & FSAM_WRITE) flags |= LFS_O_WRONLY; - - if(open_mode & FSOM_OPEN_EXISTING) flags |= 0; - if(open_mode & FSOM_OPEN_ALWAYS) flags |= LFS_O_CREAT; - if(open_mode & FSOM_OPEN_APPEND) flags |= LFS_O_CREAT | LFS_O_APPEND; - if(open_mode & FSOM_CREATE_NEW) flags |= LFS_O_CREAT | LFS_O_EXCL; - if(open_mode & FSOM_CREATE_ALWAYS) flags |= LFS_O_CREAT | LFS_O_TRUNC; - - LFSHandle* handle = lfs_handle_alloc_file(); - storage_set_storage_file_data(file, handle, storage); - - if(!enough_free_space) { - FuriString* filename; - filename = furi_string_alloc(); - path_extract_basename(path, filename); - bool is_dot_file = - (!furi_string_empty(filename) && (furi_string_get_char(filename, 0) == '.')); - furi_string_free(filename); - - /* Restrict write & creation access to all non-dot files */ - if(!is_dot_file && (flags & (LFS_O_CREAT | LFS_O_WRONLY))) { - file->internal_error_id = LFS_ERR_NOSPC; - file->error_id = FSE_DENIED; - FURI_LOG_W(TAG, "Denied access to '%s': no free space", path); - return false; - } - } - - file->internal_error_id = lfs_file_open(lfs, lfs_handle_get_file(handle), path, flags); - - if(file->internal_error_id >= LFS_ERR_OK) { - lfs_handle_set_open(handle); - } - - file->error_id = storage_int_parse_error(file->internal_error_id); - - return file->error_id == FSE_OK; -} - -static bool storage_int_file_close(void* ctx, File* file) { - StorageData* storage = ctx; - lfs_t* lfs = lfs_get_from_storage(storage); - LFSHandle* handle = storage_get_storage_file_data(file, storage); - - if(lfs_handle_is_open(handle)) { - file->internal_error_id = lfs_file_close(lfs, lfs_handle_get_file(handle)); - } else { - file->internal_error_id = LFS_ERR_BADF; - } - - file->error_id = storage_int_parse_error(file->internal_error_id); - lfs_handle_free(handle); - return file->error_id == FSE_OK; -} - -static uint16_t - storage_int_file_read(void* ctx, File* file, void* buff, uint16_t const bytes_to_read) { - StorageData* storage = ctx; - lfs_t* lfs = lfs_get_from_storage(storage); - LFSHandle* handle = storage_get_storage_file_data(file, storage); - - uint16_t bytes_read = 0; - - if(lfs_handle_is_open(handle)) { - file->internal_error_id = - lfs_file_read(lfs, lfs_handle_get_file(handle), buff, bytes_to_read); - } else { - file->internal_error_id = LFS_ERR_BADF; - } - - file->error_id = storage_int_parse_error(file->internal_error_id); - - if(file->error_id == FSE_OK) { - bytes_read = file->internal_error_id; - file->internal_error_id = 0; - } - return bytes_read; -} - -static uint16_t - storage_int_file_write(void* ctx, File* file, const void* buff, uint16_t const bytes_to_write) { - StorageData* storage = ctx; - lfs_t* lfs = lfs_get_from_storage(storage); - LFSHandle* handle = storage_get_storage_file_data(file, storage); - - uint16_t bytes_written = 0; - - if(lfs_handle_is_open(handle)) { - file->internal_error_id = - lfs_file_write(lfs, lfs_handle_get_file(handle), buff, bytes_to_write); - } else { - file->internal_error_id = LFS_ERR_BADF; - } - - file->error_id = storage_int_parse_error(file->internal_error_id); - - if(file->error_id == FSE_OK) { - bytes_written = file->internal_error_id; - file->internal_error_id = 0; - } - return bytes_written; -} - -static bool - storage_int_file_seek(void* ctx, File* file, const uint32_t offset, const bool from_start) { - StorageData* storage = ctx; - lfs_t* lfs = lfs_get_from_storage(storage); - LFSHandle* handle = storage_get_storage_file_data(file, storage); - - if(lfs_handle_is_open(handle)) { - if(from_start) { - file->internal_error_id = - lfs_file_seek(lfs, lfs_handle_get_file(handle), offset, LFS_SEEK_SET); - } else { - file->internal_error_id = - lfs_file_seek(lfs, lfs_handle_get_file(handle), offset, LFS_SEEK_CUR); - } - } else { - file->internal_error_id = LFS_ERR_BADF; - } - - file->error_id = storage_int_parse_error(file->internal_error_id); - return file->error_id == FSE_OK; -} - -static uint64_t storage_int_file_tell(void* ctx, File* file) { - StorageData* storage = ctx; - lfs_t* lfs = lfs_get_from_storage(storage); - LFSHandle* handle = storage_get_storage_file_data(file, storage); - - if(lfs_handle_is_open(handle)) { - file->internal_error_id = lfs_file_tell(lfs, lfs_handle_get_file(handle)); - } else { - file->internal_error_id = LFS_ERR_BADF; - } - - file->error_id = storage_int_parse_error(file->internal_error_id); - - int32_t position = 0; - if(file->error_id == FSE_OK) { - position = file->internal_error_id; - file->internal_error_id = 0; - } - - return position; -} - -static bool storage_int_file_expand(void* ctx, File* file, const uint64_t size) { - UNUSED(ctx); - UNUSED(file); - UNUSED(size); - file->error_id = FSE_NOT_IMPLEMENTED; - return (file->error_id == FSE_OK); -} - -static bool storage_int_file_truncate(void* ctx, File* file) { - StorageData* storage = ctx; - lfs_t* lfs = lfs_get_from_storage(storage); - LFSHandle* handle = storage_get_storage_file_data(file, storage); - - if(lfs_handle_is_open(handle)) { - file->internal_error_id = lfs_file_tell(lfs, lfs_handle_get_file(handle)); - file->error_id = storage_int_parse_error(file->internal_error_id); - - if(file->error_id == FSE_OK) { - uint32_t position = file->internal_error_id; - file->internal_error_id = - lfs_file_truncate(lfs, lfs_handle_get_file(handle), position); - file->error_id = storage_int_parse_error(file->internal_error_id); - } - } else { - file->internal_error_id = LFS_ERR_BADF; - file->error_id = storage_int_parse_error(file->internal_error_id); - } - - return file->error_id == FSE_OK; -} - -static bool storage_int_file_sync(void* ctx, File* file) { - StorageData* storage = ctx; - lfs_t* lfs = lfs_get_from_storage(storage); - LFSHandle* handle = storage_get_storage_file_data(file, storage); - - if(lfs_handle_is_open(handle)) { - file->internal_error_id = lfs_file_sync(lfs, lfs_handle_get_file(handle)); - } else { - file->internal_error_id = LFS_ERR_BADF; - } - - file->error_id = storage_int_parse_error(file->internal_error_id); - return file->error_id == FSE_OK; -} - -static uint64_t storage_int_file_size(void* ctx, File* file) { - StorageData* storage = ctx; - lfs_t* lfs = lfs_get_from_storage(storage); - LFSHandle* handle = storage_get_storage_file_data(file, storage); - - if(lfs_handle_is_open(handle)) { - file->internal_error_id = lfs_file_size(lfs, lfs_handle_get_file(handle)); - } else { - file->internal_error_id = LFS_ERR_BADF; - } - - file->error_id = storage_int_parse_error(file->internal_error_id); - - uint32_t size = 0; - if(file->error_id == FSE_OK) { - size = file->internal_error_id; - file->internal_error_id = 0; - } - - return size; -} - -static bool storage_int_file_eof(void* ctx, File* file) { - StorageData* storage = ctx; - lfs_t* lfs = lfs_get_from_storage(storage); - LFSHandle* handle = storage_get_storage_file_data(file, storage); - - bool eof = true; - - if(lfs_handle_is_open(handle)) { - int32_t position = lfs_file_tell(lfs, lfs_handle_get_file(handle)); - int32_t size = lfs_file_size(lfs, lfs_handle_get_file(handle)); - - if(position < 0) { - file->internal_error_id = position; - } else if(size < 0) { - file->internal_error_id = size; - } else { - file->internal_error_id = LFS_ERR_OK; - eof = (position >= size); - } - } else { - file->internal_error_id = LFS_ERR_BADF; - } - - file->error_id = storage_int_parse_error(file->internal_error_id); - return eof; -} - -/******************* Dir Functions *******************/ - -static bool storage_int_dir_open(void* ctx, File* file, const char* path) { - StorageData* storage = ctx; - lfs_t* lfs = lfs_get_from_storage(storage); - - LFSHandle* handle = lfs_handle_alloc_dir(); - storage_set_storage_file_data(file, handle, storage); - - file->internal_error_id = lfs_dir_open(lfs, lfs_handle_get_dir(handle), path); - if(file->internal_error_id >= LFS_ERR_OK) { - lfs_handle_set_open(handle); - } - - file->error_id = storage_int_parse_error(file->internal_error_id); - return file->error_id == FSE_OK; -} - -static bool storage_int_dir_close(void* ctx, File* file) { - StorageData* storage = ctx; - lfs_t* lfs = lfs_get_from_storage(storage); - LFSHandle* handle = storage_get_storage_file_data(file, storage); - - if(lfs_handle_is_open(handle)) { - file->internal_error_id = lfs_dir_close(lfs, lfs_handle_get_dir(handle)); - } else { - file->internal_error_id = LFS_ERR_BADF; - } - - file->error_id = storage_int_parse_error(file->internal_error_id); - lfs_handle_free(handle); - return file->error_id == FSE_OK; -} - -static bool storage_int_dir_read( - void* ctx, - File* file, - FileInfo* fileinfo, - char* name, - const uint16_t name_length) { - StorageData* storage = ctx; - lfs_t* lfs = lfs_get_from_storage(storage); - LFSHandle* handle = storage_get_storage_file_data(file, storage); - - if(lfs_handle_is_open(handle)) { - struct lfs_info _fileinfo; - - // LFS returns virtual directories "." and "..", so we read until we get something meaningful or an empty string - do { - file->internal_error_id = lfs_dir_read(lfs, lfs_handle_get_dir(handle), &_fileinfo); - file->error_id = storage_int_parse_error(file->internal_error_id); - } while(strcmp(_fileinfo.name, ".") == 0 || strcmp(_fileinfo.name, "..") == 0); - - if(fileinfo != NULL) { - fileinfo->size = _fileinfo.size; - fileinfo->flags = 0; - if(_fileinfo.type & LFS_TYPE_DIR) fileinfo->flags |= FSF_DIRECTORY; - } - - if(name != NULL) { - snprintf(name, name_length, "%s", _fileinfo.name); - } - - // set FSE_NOT_EXIST error on end of directory - if(file->internal_error_id == 0) { - file->error_id = FSE_NOT_EXIST; - } - } else { - file->internal_error_id = LFS_ERR_BADF; - file->error_id = storage_int_parse_error(file->internal_error_id); - } - - return file->error_id == FSE_OK; -} - -static bool storage_int_dir_rewind(void* ctx, File* file) { - StorageData* storage = ctx; - lfs_t* lfs = lfs_get_from_storage(storage); - LFSHandle* handle = storage_get_storage_file_data(file, storage); - - if(lfs_handle_is_open(handle)) { - file->internal_error_id = lfs_dir_rewind(lfs, lfs_handle_get_dir(handle)); - } else { - file->internal_error_id = LFS_ERR_BADF; - } - - file->error_id = storage_int_parse_error(file->internal_error_id); - return file->error_id == FSE_OK; -} - -/******************* Common FS Functions *******************/ - -static FS_Error storage_int_common_stat(void* ctx, const char* path, FileInfo* fileinfo) { - StorageData* storage = ctx; - lfs_t* lfs = lfs_get_from_storage(storage); - struct lfs_info _fileinfo; - int result = lfs_stat(lfs, path, &_fileinfo); - - if(fileinfo != NULL) { - fileinfo->size = _fileinfo.size; - fileinfo->flags = 0; - if(_fileinfo.type & LFS_TYPE_DIR) fileinfo->flags |= FSF_DIRECTORY; - } - - return storage_int_parse_error(result); -} - -static FS_Error storage_int_common_remove(void* ctx, const char* path) { - StorageData* storage = ctx; - lfs_t* lfs = lfs_get_from_storage(storage); - int result = lfs_remove(lfs, path); - return storage_int_parse_error(result); -} - -static FS_Error storage_int_common_rename(void* ctx, const char* old, const char* new) { - StorageData* storage = ctx; - lfs_t* lfs = lfs_get_from_storage(storage); - int result = lfs_rename(lfs, old, new); - return storage_int_parse_error(result); -} - -static FS_Error storage_int_common_mkdir(void* ctx, const char* path) { - StorageData* storage = ctx; - lfs_t* lfs = lfs_get_from_storage(storage); - int result = lfs_mkdir(lfs, path); - return storage_int_parse_error(result); -} - -static FS_Error storage_int_common_fs_info( - void* ctx, - const char* fs_path, - uint64_t* total_space, - uint64_t* free_space) { - UNUSED(fs_path); - StorageData* storage = ctx; - - lfs_t* lfs = lfs_get_from_storage(storage); - LFSData* lfs_data = lfs_data_get_from_storage(storage); - - if(total_space) { - *total_space = lfs_data->config.block_size * lfs_data->config.block_count; - } - - lfs_ssize_t result = lfs_fs_size(lfs); - if(free_space && (result >= 0)) { - *free_space = (lfs_data->config.block_count - result) * lfs_data->config.block_size; - } - - return storage_int_parse_error(result); -} - -static bool storage_int_common_equivalent_path(const char* path1, const char* path2) { - return strcmp(path1, path2) == 0; -} - -/******************* Init Storage *******************/ -static const FS_Api fs_api = { - .file = - { - .open = storage_int_file_open, - .close = storage_int_file_close, - .read = storage_int_file_read, - .write = storage_int_file_write, - .seek = storage_int_file_seek, - .tell = storage_int_file_tell, - .expand = storage_int_file_expand, - .truncate = storage_int_file_truncate, - .size = storage_int_file_size, - .sync = storage_int_file_sync, - .eof = storage_int_file_eof, - }, - .dir = - { - .open = storage_int_dir_open, - .close = storage_int_dir_close, - .read = storage_int_dir_read, - .rewind = storage_int_dir_rewind, - }, - .common = - { - .stat = storage_int_common_stat, - .mkdir = storage_int_common_mkdir, - .remove = storage_int_common_remove, - .rename = storage_int_common_rename, - .fs_info = storage_int_common_fs_info, - .equivalent_path = storage_int_common_equivalent_path, - }, -}; - -void storage_int_init(StorageData* storage) { - FURI_LOG_I(TAG, "Starting"); - LFSData* lfs_data = storage_int_lfs_data_alloc(); - FURI_LOG_I( - TAG, - "Config: start %p, read %lu, write %lu, page size: %lu, page count: %lu, cycles: %ld", - (void*)lfs_data->start_address, - lfs_data->config.read_size, - lfs_data->config.prog_size, - lfs_data->config.block_size, - lfs_data->config.block_count, - lfs_data->config.block_cycles); - - storage_int_lfs_mount(lfs_data, storage); - - storage->data = lfs_data; - storage->api.tick = NULL; - storage->fs_api = &fs_api; -} diff --git a/applications/services/storage/storages/storage_int.h b/applications/services/storage/storages/storage_int.h deleted file mode 100644 index 456d72408..000000000 --- a/applications/services/storage/storages/storage_int.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include -#include "../storage_glue.h" - -#ifdef __cplusplus -extern "C" { -#endif - -void storage_int_init(StorageData* storage); - -#ifdef __cplusplus -} -#endif diff --git a/applications/settings/about/about.c b/applications/settings/about/about.c index 710668fc4..c5f839ec6 100644 --- a/applications/settings/about/about.c +++ b/applications/settings/about/about.c @@ -1,9 +1,12 @@ #include -#include + #include -#include +#include #include + +#include #include + #include #include #include @@ -210,7 +213,8 @@ const AboutDialogScreen about_screens[] = { about_screen_cert_china_0, about_screen_cert_china_1, about_screen_cert_taiwan, - about_screen_cert_mexico}; + about_screen_cert_mexico, +}; int32_t about_settings_app(void* p) { UNUSED(p); @@ -218,18 +222,15 @@ int32_t about_settings_app(void* p) { DialogMessage* message = dialog_message_alloc(); Gui* gui = furi_record_open(RECORD_GUI); - ViewDispatcher* view_dispatcher = view_dispatcher_alloc(); + ViewHolder* view_holder = view_holder_alloc(); EmptyScreen* empty_screen = empty_screen_alloc(); - const uint32_t empty_screen_index = 0; size_t screen_index = 0; DialogMessageButton screen_result; // draw empty screen to prevent menu flickering - view_dispatcher_add_view( - view_dispatcher, empty_screen_index, empty_screen_get_view(empty_screen)); - view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen); - view_dispatcher_switch_to_view(view_dispatcher, empty_screen_index); + view_holder_attach_to_gui(view_holder, gui); + view_holder_set_view(view_holder, empty_screen_get_view(empty_screen)); int32_t ret = 0; while(1) { @@ -266,8 +267,8 @@ int32_t about_settings_app(void* p) { dialog_message_free(message); furi_record_close(RECORD_DIALOGS); - view_dispatcher_remove_view(view_dispatcher, empty_screen_index); - view_dispatcher_free(view_dispatcher); + view_holder_set_view(view_holder, NULL); + view_holder_free(view_holder); empty_screen_free(empty_screen); furi_record_close(RECORD_GUI); diff --git a/applications/settings/bt_settings_app/bt_settings_app.c b/applications/settings/bt_settings_app/bt_settings_app.c index 93be2dcfe..174d0bcbb 100644 --- a/applications/settings/bt_settings_app/bt_settings_app.c +++ b/applications/settings/bt_settings_app/bt_settings_app.c @@ -15,14 +15,12 @@ static bool bt_settings_back_event_callback(void* context) { BtSettingsApp* bt_settings_app_alloc(void) { BtSettingsApp* app = malloc(sizeof(BtSettingsApp)); - // Load settings app->gui = furi_record_open(RECORD_GUI); app->bt = furi_record_open(RECORD_BT); // View Dispatcher and Scene Manager app->view_dispatcher = view_dispatcher_alloc(); app->scene_manager = scene_manager_alloc(&bt_settings_scene_handlers, app); - view_dispatcher_enable_queue(app->view_dispatcher); view_dispatcher_set_event_callback_context(app->view_dispatcher, app); view_dispatcher_set_custom_event_callback( @@ -47,6 +45,8 @@ BtSettingsApp* bt_settings_app_alloc(void) { view_dispatcher_add_view( app->view_dispatcher, BtSettingsAppViewPopup, popup_get_view(app->popup)); + bt_get_settings(app->bt, &app->settings); + // Set first scene scene_manager_next_scene(app->scene_manager, BtSettingsAppSceneStart); return app; @@ -54,6 +54,7 @@ BtSettingsApp* bt_settings_app_alloc(void) { void bt_settings_app_free(BtSettingsApp* app) { furi_assert(app); + bt_set_settings(app->bt, &app->settings); // Gui modules view_dispatcher_remove_view(app->view_dispatcher, BtSettingsAppViewVarItemList); variable_item_list_free(app->var_item_list); @@ -78,7 +79,6 @@ extern int32_t bt_settings_app(void* p) { UNUSED(p); BtSettingsApp* app = bt_settings_app_alloc(); view_dispatcher_run(app->view_dispatcher); - bt_settings_save(&app->bt->bt_settings); bt_settings_app_free(app); return 0; } diff --git a/applications/settings/bt_settings_app/bt_settings_app.h b/applications/settings/bt_settings_app/bt_settings_app.h index 4dc20b020..5255945ff 100644 --- a/applications/settings/bt_settings_app/bt_settings_app.h +++ b/applications/settings/bt_settings_app/bt_settings_app.h @@ -1,19 +1,21 @@ #pragma once #include -#include -#include + #include #include #include #include -#include #include #include #include -#include +#include +#include + +#include + #include "scenes/bt_settings_scene.h" enum BtSettingsCustomEvent { @@ -25,6 +27,7 @@ enum BtSettingsCustomEvent { }; typedef struct { + BtSettings settings; Bt* bt; Gui* gui; SceneManager* scene_manager; diff --git a/applications/settings/bt_settings_app/mock_imports/mock_bt_api.c b/applications/settings/bt_settings_app/mock_imports/mock_bt_api.c new file mode 100644 index 000000000..c7a2036f1 --- /dev/null +++ b/applications/settings/bt_settings_app/mock_imports/mock_bt_api.c @@ -0,0 +1,7 @@ +// Since settings app is external, it cannot access firmware functions +// For simple utils like this, easier to include C code in app rather than exposing to API +// Instead of copying the file, can (ab)use the preprocessor to insert the source code here +// Then, we still use the Header from original code as if nothing happened + +// bt_get_settings(), bt_set_settings() +#include diff --git a/applications/settings/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c b/applications/settings/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c index acf961967..cfc945751 100644 --- a/applications/settings/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c +++ b/applications/settings/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c @@ -37,7 +37,10 @@ bool bt_settings_scene_forget_dev_confirm_on_event(void* context, SceneManagerEv const char* keys_paths[] = { BAD_KB_KEYS_PATH, EXT_PATH("apps_data/hid_ble/.bt_hid.keys"), - EXT_PATH("apps_data/totp/.bt_hid.keys"), + EXT_PATH("apps_data/air_mouse/.bt_hid.keys"), + EXT_PATH("apps_data/vgm_air_mouse/.bt_hid.keys"), + EXT_PATH("apps_data/pc_monitor/.bt_serial.keys"), + EXT_PATH("apps_data/totp/.bt_hid_00.keys"), }; Storage* storage = furi_record_open(RECORD_STORAGE); for(size_t i = 0; i < COUNT_OF(keys_paths); i++) { diff --git a/applications/settings/bt_settings_app/scenes/bt_settings_scene_start.c b/applications/settings/bt_settings_app/scenes/bt_settings_scene_start.c index e39887e02..a76740bd1 100644 --- a/applications/settings/bt_settings_app/scenes/bt_settings_scene_start.c +++ b/applications/settings/bt_settings_app/scenes/bt_settings_scene_start.c @@ -46,7 +46,7 @@ void bt_settings_scene_start_on_enter(void* context) { BtSettingNum, bt_settings_scene_start_var_list_change_callback, app); - if(app->bt->bt_settings.enabled) { + if(app->settings.enabled) { variable_item_set_current_value_index(item, BtSettingOn); variable_item_set_current_value_text(item, bt_settings_text[BtSettingOn]); } else { @@ -70,18 +70,17 @@ bool bt_settings_scene_start_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == BtSettingOn) { - furi_hal_bt_start_advertising(); - app->bt->bt_settings.enabled = true; + app->settings.enabled = true; consumed = true; } else if(event.event == BtSettingOff) { - app->bt->bt_settings.enabled = false; - furi_hal_bt_stop_advertising(); + app->settings.enabled = false; consumed = true; } else if(event.event == BtSettingsCustomEventForgetDevices) { scene_manager_next_scene(app->scene_manager, BtSettingsAppSceneForgetDevConfirm); consumed = true; } } + return consumed; } diff --git a/applications/settings/desktop_settings/desktop_settings_app.c b/applications/settings/desktop_settings/desktop_settings_app.c index cb1053414..71b42f81a 100644 --- a/applications/settings/desktop_settings/desktop_settings_app.c +++ b/applications/settings/desktop_settings/desktop_settings_app.c @@ -2,9 +2,11 @@ #include #include +#include +#include + #include "desktop_settings_app.h" #include "scenes/desktop_settings_scene.h" -#include const char* EXTRA_KEYBINDS[] = { "Apps Menu", @@ -31,51 +33,30 @@ static bool desktop_settings_back_event_callback(void* context) { return scene_manager_handle_back_event(app->scene_manager); } -const char* desktop_settings_app_get_keybind(DesktopSettingsApp* app) { - KeybindType type = +FuriString* desktop_settings_app_get_keybind(DesktopSettingsApp* app) { + DesktopKeybindType type = scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppSceneKeybindsType); - KeybindKey key = + DesktopKeybindKey key = scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppSceneKeybindsKey); - return app->desktop->keybinds[type][key].data; + return app->keybinds[type][key]; } -bool desktop_settings_app_set_keybind(DesktopSettingsApp* app, const char* value) { - if(strnlen(value, MAX_KEYBIND_LENGTH) == MAX_KEYBIND_LENGTH) { - // No NULL terminator, value is too long for keybind - DialogMessage* message = dialog_message_alloc(); - dialog_message_set_header(message, "Keybind Too Long", 64, 0, AlignCenter, AlignTop); - dialog_message_set_buttons(message, NULL, "Ok", NULL); - dialog_message_set_text( - message, - "Keybinds are max 63 chars.\n" - "Shorten the file path or\n" - "choose something else.", - 64, - 32, - AlignCenter, - AlignCenter); - dialog_message_show(app->dialogs, message); - dialog_message_free(message); - return false; - } - KeybindType type = +void desktop_settings_app_set_keybind(DesktopSettingsApp* app, const char* value) { + DesktopKeybindType type = scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppSceneKeybindsType); - KeybindKey key = + DesktopKeybindKey key = scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppSceneKeybindsKey); - strlcpy(app->desktop->keybinds[type][key].data, value, MAX_KEYBIND_LENGTH); - DESKTOP_KEYBINDS_SAVE(&app->desktop->keybinds, sizeof(app->desktop->keybinds)); - return true; + furi_string_set(app->keybinds[type][key], value); + app->save_keybinds = true; } DesktopSettingsApp* desktop_settings_app_alloc(void) { DesktopSettingsApp* app = malloc(sizeof(DesktopSettingsApp)); app->gui = furi_record_open(RECORD_GUI); - app->desktop = furi_record_open(RECORD_DESKTOP); app->dialogs = furi_record_open(RECORD_DIALOGS); app->view_dispatcher = view_dispatcher_alloc(); app->scene_manager = scene_manager_alloc(&desktop_settings_scene_handlers, app); - view_dispatcher_enable_queue(app->view_dispatcher); view_dispatcher_set_event_callback_context(app->view_dispatcher, app); view_dispatcher_set_custom_event_callback( @@ -140,13 +121,16 @@ void desktop_settings_app_free(DesktopSettingsApp* app) { scene_manager_free(app->scene_manager); // Records furi_record_close(RECORD_DIALOGS); - furi_record_close(RECORD_DESKTOP); furi_record_close(RECORD_GUI); free(app); } extern int32_t desktop_settings_app(void* p) { DesktopSettingsApp* app = desktop_settings_app_alloc(); + Desktop* desktop = furi_record_open(RECORD_DESKTOP); + + desktop_api_get_settings(desktop, &app->settings); + desktop_keybinds_load(desktop, &app->keybinds); if(p && (strcmp(p, DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG) == 0)) { scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinSetupHowto); @@ -156,9 +140,13 @@ extern int32_t desktop_settings_app(void* p) { view_dispatcher_run(app->view_dispatcher); - if(app->save_settings) { - DESKTOP_SETTINGS_SAVE(&app->desktop->settings); + if(app->save_keybinds) { + desktop_keybinds_save(desktop, &app->keybinds); } + desktop_keybinds_free(&app->keybinds); + desktop_api_set_settings(desktop, &app->settings); + furi_record_close(RECORD_DESKTOP); + desktop_settings_app_free(app); return 0; diff --git a/applications/settings/desktop_settings/desktop_settings_app.h b/applications/settings/desktop_settings/desktop_settings_app.h index 7d267df4f..d989426e4 100644 --- a/applications/settings/desktop_settings/desktop_settings_app.h +++ b/applications/settings/desktop_settings/desktop_settings_app.h @@ -9,8 +9,11 @@ #include #include #include +#include -#include +#include +#include +#include #include #include "views/desktop_settings_view_pin_setup_howto.h" #include "views/desktop_settings_view_pin_setup_howto2.h" @@ -37,7 +40,8 @@ extern const char* EXTRA_KEYBINDS[]; extern const size_t EXTRA_KEYBINDS_COUNT; typedef struct { - Desktop* desktop; + DesktopSettings settings; + DesktopKeybinds keybinds; Gui* gui; DialogsApp* dialogs; @@ -51,13 +55,13 @@ typedef struct { DesktopSettingsViewPinSetupHowto* pin_setup_howto_view; DesktopSettingsViewPinSetupHowto2* pin_setup_howto2_view; - PinCode pincode_buffer; + DesktopPinCode pincode_buffer; bool pincode_buffer_filled; uint32_t pin_menu_idx; - bool save_settings; + bool save_keybinds; } DesktopSettingsApp; -const char* desktop_settings_app_get_keybind(DesktopSettingsApp* app); -bool desktop_settings_app_set_keybind(DesktopSettingsApp* app, const char* value); +FuriString* desktop_settings_app_get_keybind(DesktopSettingsApp* app); +void desktop_settings_app_set_keybind(DesktopSettingsApp* app, const char* value); diff --git a/applications/settings/desktop_settings/helpers/pin.c b/applications/settings/desktop_settings/helpers/pin.c deleted file mode 100644 index 2e2791971..000000000 --- a/applications/settings/desktop_settings/helpers/pin.c +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/applications/settings/desktop_settings/mock_imports/mock_desktop.c b/applications/settings/desktop_settings/mock_imports/mock_desktop.c new file mode 100644 index 000000000..e46770596 --- /dev/null +++ b/applications/settings/desktop_settings/mock_imports/mock_desktop.c @@ -0,0 +1,7 @@ +// Since settings app is external, it cannot access firmware functions +// For simple utils like this, easier to include C code in app rather than exposing to API +// Instead of copying the file, can (ab)use the preprocessor to insert the source code here +// Then, we still use the Header from original code as if nothing happened + +// desktop_api_get_settings(), desktop_api_set_settings() +#include diff --git a/applications/settings/desktop_settings/mock_imports/mock_desktop_keybinds.c b/applications/settings/desktop_settings/mock_imports/mock_desktop_keybinds.c new file mode 100644 index 000000000..900c6c485 --- /dev/null +++ b/applications/settings/desktop_settings/mock_imports/mock_desktop_keybinds.c @@ -0,0 +1,7 @@ +// Since settings app is external, it cannot access firmware functions +// For simple utils like this, easier to include C code in app rather than exposing to API +// Instead of copying the file, can (ab)use the preprocessor to insert the source code here +// Then, we still use the Header from original code as if nothing happened + +// desktop_keybinds_free(), desktop_keybinds_load(), desktop_keybinds_save() +#include diff --git a/applications/settings/desktop_settings/mock_imports/mock_desktop_view_pin_input.c b/applications/settings/desktop_settings/mock_imports/mock_desktop_view_pin_input.c new file mode 100644 index 000000000..3d356dfde --- /dev/null +++ b/applications/settings/desktop_settings/mock_imports/mock_desktop_view_pin_input.c @@ -0,0 +1,7 @@ +// Since settings app is external, it cannot access firmware functions +// For simple utils like this, easier to include C code in app rather than exposing to API +// Instead of copying the file, can (ab)use the preprocessor to insert the source code here +// Then, we still use the Header from original code as if nothing happened + +// desktop_view_pin_input_get_view(), desktop_view_pin_input_set_back_callback(), desktop_view_pin_input_set_label_secondary(), desktop_view_pin_input_set_pin(), desktop_view_pin_input_set_context(), desktop_view_pin_input_set_label_button(), desktop_view_pin_input_unlock_input(), desktop_view_pin_input_set_pin_position(), desktop_view_pin_input_set_label_primary(), desktop_view_pin_input_reset_pin(), desktop_view_pin_input_set_done_callback(), desktop_view_pin_input_lock_input(), desktop_view_pin_input_alloc(), desktop_view_pin_input_free() +#include diff --git a/applications/settings/desktop_settings/mock_imports/mock_furi_hal_rtc.c b/applications/settings/desktop_settings/mock_imports/mock_furi_hal_rtc.c new file mode 100644 index 000000000..7cadba5a0 --- /dev/null +++ b/applications/settings/desktop_settings/mock_imports/mock_furi_hal_rtc.c @@ -0,0 +1,7 @@ +// Since settings app is external, it cannot access firmware functions +// For simple utils like this, easier to include C code in app rather than exposing to API +// Instead of copying the file, can (ab)use the preprocessor to insert the source code here +// Then, we still use the Header from original code as if nothing happened + +// furi_hal_rtc_get_pin_value(), furi_hal_rtc_set_pin_value() +#include diff --git a/applications/settings/desktop_settings/mock_imports/mock_pin_code.c b/applications/settings/desktop_settings/mock_imports/mock_pin_code.c new file mode 100644 index 000000000..ae092b90a --- /dev/null +++ b/applications/settings/desktop_settings/mock_imports/mock_pin_code.c @@ -0,0 +1,7 @@ +// Since settings app is external, it cannot access firmware functions +// For simple utils like this, easier to include C code in app rather than exposing to API +// Instead of copying the file, can (ab)use the preprocessor to insert the source code here +// Then, we still use the Header from original code as if nothing happened + +// desktop_pin_code_is_set(), desktop_pin_code_reset(), desktop_pin_code_check(), desktop_pin_code_is_equal(), desktop_pin_code_set(), desktop_pin_lock_error_notify() +#include diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_action.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_action.c index 40f4fc656..66faff66d 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_action.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_action.c @@ -6,16 +6,15 @@ static void desktop_settings_scene_keybinds_action_submenu_callback(void* context, uint32_t index) { DesktopSettingsApp* app = context; - if(desktop_settings_app_set_keybind(app, (const char*)index)) { - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, DesktopSettingsAppSceneStart); - } + desktop_settings_app_set_keybind(app, (const char*)index); + scene_manager_search_and_switch_to_previous_scene( + app->scene_manager, DesktopSettingsAppSceneStart); } void desktop_settings_scene_keybinds_action_on_enter(void* context) { DesktopSettingsApp* app = context; Submenu* submenu = app->submenu; - const char* keybind = desktop_settings_app_get_keybind(app); + FuriString* keybind = desktop_settings_app_get_keybind(app); submenu_reset(submenu); uint32_t pre_select_item = 0; @@ -32,7 +31,7 @@ void desktop_settings_scene_keybinds_action_on_enter(void* context) { app); // Select keybind item in submenu - if(!strncmp(FLIPPER_APPS[i].name, keybind, MAX_KEYBIND_LENGTH)) { + if(furi_string_equal(keybind, FLIPPER_APPS[i].name)) { pre_select_item = (uint32_t)FLIPPER_APPS[i].name; } } @@ -45,7 +44,7 @@ void desktop_settings_scene_keybinds_action_on_enter(void* context) { app); // Select keybind item in submenu - if(!strncmp(FLIPPER_EXTERNAL_APPS[i].name, keybind, MAX_KEYBIND_LENGTH)) { + if(furi_string_equal(keybind, FLIPPER_EXTERNAL_APPS[i].name)) { pre_select_item = (uint32_t)FLIPPER_EXTERNAL_APPS[i].name; } } @@ -59,7 +58,7 @@ void desktop_settings_scene_keybinds_action_on_enter(void* context) { app); // Select keybind item in submenu - if(!strncmp(EXTRA_KEYBINDS[i], keybind, MAX_KEYBIND_LENGTH)) { + if(furi_string_equal(keybind, EXTRA_KEYBINDS[i])) { pre_select_item = (uint32_t)EXTRA_KEYBINDS[i]; } } diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_action_type.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_action_type.c index d0e8ac74d..6637d9f2b 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_action_type.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_action_type.c @@ -23,7 +23,7 @@ static void DesktopSettingsApp* app = context; scene_manager_set_scene_state( app->scene_manager, DesktopSettingsAppSceneKeybindsActionType, index); - const char* keybind = desktop_settings_app_get_keybind(app); + FuriString* keybind = desktop_settings_app_get_keybind(app); switch(index) { case DesktopSettingsAppKeybindActionTypeMainApp: @@ -55,24 +55,22 @@ static void .base_path = base_path, }; FuriString* temp_path = furi_string_alloc_set_str(base_path); - if(storage_file_exists(furi_record_open(RECORD_STORAGE), keybind)) { - furi_string_set_str(temp_path, keybind); + if(storage_file_exists(furi_record_open(RECORD_STORAGE), furi_string_get_cstr(keybind))) { + furi_string_set(temp_path, keybind); } furi_record_close(RECORD_STORAGE); if(dialog_file_browser_show(app->dialogs, temp_path, temp_path, &browser_options)) { - if(desktop_settings_app_set_keybind(app, furi_string_get_cstr(temp_path))) { - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, DesktopSettingsAppSceneStart); - } + desktop_settings_app_set_keybind(app, furi_string_get_cstr(temp_path)); + scene_manager_search_and_switch_to_previous_scene( + app->scene_manager, DesktopSettingsAppSceneStart); } furi_string_free(temp_path); break; } case DesktopSettingsAppKeybindActionTypeRemoveKeybind: - if(desktop_settings_app_set_keybind(app, "")) { - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, DesktopSettingsAppSceneStart); - } + desktop_settings_app_set_keybind(app, ""); + scene_manager_search_and_switch_to_previous_scene( + app->scene_manager, DesktopSettingsAppSceneStart); break; default: break; @@ -82,7 +80,7 @@ static void void desktop_settings_scene_keybinds_action_type_on_enter(void* context) { DesktopSettingsApp* app = context; Submenu* submenu = app->submenu; - const char* keybind = desktop_settings_app_get_keybind(app); + FuriString* keybind = desktop_settings_app_get_keybind(app); submenu_add_item( submenu, @@ -123,34 +121,32 @@ void desktop_settings_scene_keybinds_action_type_on_enter(void* context) { app->scene_manager, DesktopSettingsAppSceneKeybindsActionType); if(selected == DesktopSettingsAppKeybindActionTypeRemoveKeybind) { for(size_t i = 0; i < FLIPPER_APPS_COUNT; i++) { - if(!strncmp(FLIPPER_APPS[i].name, keybind, MAX_KEYBIND_LENGTH)) { + if(furi_string_equal(keybind, FLIPPER_APPS[i].name)) { selected = DesktopSettingsAppKeybindActionTypeMainApp; } } for(size_t i = 0; i < FLIPPER_EXTERNAL_APPS_COUNT; i++) { - if(!strncmp(FLIPPER_EXTERNAL_APPS[i].name, keybind, MAX_KEYBIND_LENGTH)) { + if(furi_string_equal(keybind, FLIPPER_EXTERNAL_APPS[i].name)) { selected = DesktopSettingsAppKeybindActionTypeMainApp; } } - if(storage_file_exists(furi_record_open(RECORD_STORAGE), keybind)) { - FuriString* tmp = furi_string_alloc_set(keybind); - if(furi_string_end_with_str(tmp, ".fap")) { + if(storage_file_exists(furi_record_open(RECORD_STORAGE), furi_string_get_cstr(keybind))) { + if(furi_string_end_with_str(keybind, ".fap")) { selected = DesktopSettingsAppKeybindActionTypeExternalApp; } else { selected = DesktopSettingsAppKeybindActionTypeOpenFile; } - furi_string_free(tmp); } furi_record_close(RECORD_STORAGE); for(size_t i = 0; i < EXTRA_KEYBINDS_COUNT; i++) { - if(!strncmp(EXTRA_KEYBINDS[i], keybind, MAX_KEYBIND_LENGTH)) { + if(furi_string_equal(keybind, EXTRA_KEYBINDS[i])) { selected = DesktopSettingsAppKeybindActionTypeMoreActions; } } - if(!strnlen(keybind, MAX_KEYBIND_LENGTH)) { + if(furi_string_empty(keybind)) { selected = DesktopSettingsAppKeybindActionTypeRemoveKeybind; } } diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_key.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_key.c index 7ac1e72f5..a2a1f8a76 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_key.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_key.c @@ -13,21 +13,33 @@ void desktop_settings_scene_keybinds_key_on_enter(void* context) { Submenu* submenu = app->submenu; submenu_reset(submenu); - submenu_add_item( - submenu, "Up", KeybindKeyUp, desktop_settings_scene_keybinds_key_submenu_callback, app); - - submenu_add_item( - submenu, "Down", KeybindKeyDown, desktop_settings_scene_keybinds_key_submenu_callback, app); - submenu_add_item( submenu, - "Right", - KeybindKeyRight, + "Up", + DesktopKeybindKeyUp, desktop_settings_scene_keybinds_key_submenu_callback, app); submenu_add_item( - submenu, "Left", KeybindKeyLeft, desktop_settings_scene_keybinds_key_submenu_callback, app); + submenu, + "Down", + DesktopKeybindKeyDown, + desktop_settings_scene_keybinds_key_submenu_callback, + app); + + submenu_add_item( + submenu, + "Right", + DesktopKeybindKeyRight, + desktop_settings_scene_keybinds_key_submenu_callback, + app); + + submenu_add_item( + submenu, + "Left", + DesktopKeybindKeyLeft, + desktop_settings_scene_keybinds_key_submenu_callback, + app); submenu_set_header(submenu, "Keybind key:"); diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_reset.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_reset.c index 99d70f662..4acf9daf9 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_reset.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_reset.c @@ -33,7 +33,10 @@ bool desktop_settings_scene_keybinds_reset_on_event(void* context, SceneManagerE case DialogExResultRight: storage_common_remove(furi_record_open(RECORD_STORAGE), DESKTOP_KEYBINDS_PATH); furi_record_close(RECORD_STORAGE); - DESKTOP_KEYBINDS_LOAD(&app->desktop->keybinds, sizeof(app->desktop->keybinds)); + desktop_keybinds_free(&app->keybinds); + desktop_keybinds_load(furi_record_open(RECORD_DESKTOP), &app->keybinds); + furi_record_close(RECORD_DESKTOP); + app->save_keybinds = false; /* fall through */ case DialogExResultLeft: consumed = scene_manager_previous_scene(app->scene_manager); diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_type.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_type.c index 645f88738..8d52e6ffa 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_type.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_type.c @@ -16,14 +16,14 @@ void desktop_settings_scene_keybinds_type_on_enter(void* context) { submenu_add_item( submenu, "Press", - KeybindTypePress, + DesktopKeybindTypePress, desktop_settings_scene_keybinds_type_submenu_callback, app); submenu_add_item( submenu, "Hold", - KeybindTypeHold, + DesktopKeybindTypeHold, desktop_settings_scene_keybinds_type_submenu_callback, app); diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_auth.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_auth.c index c2d9e96ff..1e6416531 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_auth.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_auth.c @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include "../desktop_settings_app.h" #include #include @@ -12,13 +12,14 @@ #define SCENE_EVENT_PINS_EQUAL (1U) #define SCENE_EVENT_PINS_DIFFERENT (2U) -static void pin_auth_done_callback(const PinCode* pin_code, void* context) { +static void pin_auth_done_callback(const DesktopPinCode* pin_code, void* context) { furi_assert(pin_code); furi_assert(context); - DesktopSettingsApp* app = context; + DesktopSettingsApp* app = context; app->pincode_buffer = *pin_code; - if(desktop_pin_compare(&app->desktop->settings.pin_code, pin_code)) { + + if(desktop_pin_code_check(pin_code)) { view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_PINS_EQUAL); } else { view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_PINS_DIFFERENT); @@ -31,9 +32,9 @@ static void pin_auth_back_callback(void* context) { } void desktop_settings_scene_pin_auth_on_enter(void* context) { - DesktopSettingsApp* app = context; + furi_assert(desktop_pin_code_is_set()); - furi_assert(desktop_pin_is_valid(&app->desktop->settings.pin_code)); + DesktopSettingsApp* app = context; desktop_view_pin_input_set_context(app->pin_input_view, app); desktop_view_pin_input_set_back_callback(app->pin_input_view, pin_auth_back_callback); diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_disable.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_disable.c index 976baec09..abcce66da 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_disable.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_disable.c @@ -17,10 +17,8 @@ static void pin_disable_back_callback(void* context) { void desktop_settings_scene_pin_disable_on_enter(void* context) { furi_assert(context); DesktopSettingsApp* app = context; - app->desktop->settings.pin_code.length = 0; - memset( - app->desktop->settings.pin_code.data, '0', sizeof(app->desktop->settings.pin_code.data)); - app->save_settings = true; + + desktop_pin_code_reset(); popup_set_context(app->popup, app); popup_set_callback(app->popup, pin_disable_back_callback); diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_error.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_error.c index 1ba3c1b2d..711683c3f 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_error.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_error.c @@ -6,7 +6,7 @@ #include #include "desktop_settings_scene.h" #include "desktop_settings_scene_i.h" -#include +#include #include "../desktop_settings_app.h" #define SCENE_EVENT_EXIT (0U) @@ -17,7 +17,7 @@ static void pin_error_back_callback(void* context) { view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_EXIT); } -static void pin_error_done_callback(const PinCode* pin_code, void* context) { +static void pin_error_done_callback(const DesktopPinCode* pin_code, void* context) { UNUSED(pin_code); furi_assert(context); DesktopSettingsApp* app = context; diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_menu.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_menu.c index 92228bfbb..e0c66cb28 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_menu.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_menu.c @@ -4,7 +4,6 @@ #include "../desktop_settings_app.h" #include "desktop_settings_scene.h" #include "desktop_settings_scene_i.h" -#include "desktop/helpers/pin.h" #define SCENE_EVENT_SET_PIN 0 #define SCENE_EVENT_CHANGE_PIN 1 @@ -20,7 +19,7 @@ void desktop_settings_scene_pin_menu_on_enter(void* context) { Submenu* submenu = app->submenu; submenu_reset(submenu); - if(!desktop_pin_is_valid(&app->desktop->settings.pin_code)) { + if(!desktop_pin_code_is_set()) { submenu_add_item( submenu, "Set PIN", diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup.c index 93012330a..08f5fcb3f 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup.c @@ -7,14 +7,14 @@ #include #include "desktop_settings_scene.h" #include "desktop_settings_scene_i.h" -#include +#include #define SCENE_EVENT_EXIT (0U) #define SCENE_EVENT_1ST_PIN_ENTERED (1U) #define SCENE_EVENT_PINS_EQUAL (2U) #define SCENE_EVENT_PINS_DIFFERENT (3U) -static void pin_setup_done_callback(const PinCode* pin_code, void* context) { +static void pin_setup_done_callback(const DesktopPinCode* pin_code, void* context) { furi_assert(pin_code); furi_assert(context); DesktopSettingsApp* app = context; @@ -25,7 +25,7 @@ static void pin_setup_done_callback(const PinCode* pin_code, void* context) { view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_1ST_PIN_ENTERED); } else { app->pincode_buffer_filled = false; - if(desktop_pin_compare(&app->pincode_buffer, pin_code)) { + if(desktop_pin_code_is_equal(&app->pincode_buffer, pin_code)) { view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_PINS_EQUAL); } else { view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_PINS_DIFFERENT); diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_done.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_done.c index 2f60dac8e..aa3d2214e 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_done.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_done.c @@ -11,7 +11,7 @@ #define SCENE_EVENT_DONE (0U) -static void pin_setup_done_callback(const PinCode* pin_code, void* context) { +static void pin_setup_done_callback(const DesktopPinCode* pin_code, void* context) { furi_assert(pin_code); furi_assert(context); DesktopSettingsApp* app = context; @@ -22,6 +22,8 @@ static void pin_setup_done_callback(const PinCode* pin_code, void* context) { void desktop_settings_scene_pin_setup_done_on_enter(void* context) { DesktopSettingsApp* app = context; + desktop_pin_code_set(&app->pincode_buffer); + NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); notification_message(notification, &sequence_single_vibro); notification_message(notification, &sequence_blink_green_10); @@ -47,8 +49,6 @@ bool desktop_settings_scene_pin_setup_done_on_event(void* context, SceneManagerE if(event.type == SceneManagerEventTypeCustom) { switch(event.event) { case SCENE_EVENT_DONE: { - memcpy(&app->desktop->settings.pin_code, &app->pincode_buffer, sizeof(PinCode)); - app->save_settings = true; bool scene_found = false; scene_found = scene_manager_search_and_switch_to_previous_scene( app->scene_manager, DesktopSettingsAppScenePinMenu); diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c index cc331e586..0edd48a58 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c @@ -4,16 +4,17 @@ #include "../desktop_settings_app.h" #include "desktop_settings_scene.h" -enum VarItemListIndex { - VarItemListIndexKeybinds, - VarItemListIndexResetKeybinds, - VarItemListIndexPinSetup, - VarItemListIndexAutoLockTime, - VarItemListIndexAutoLockPin, -}; +typedef enum { + DesktopSettingsPinSetup = 0, + DesktopSettingsKeybindSetup, + DesktopSettingsResetKeybinds, + DesktopSettingsAutoLockDelay, + DesktopSettingsAutoLockPin, + DesktopSettingsClockDisplay, +} DesktopSettingsEntry; #define AUTO_LOCK_DELAY_COUNT 9 -const char* const auto_lock_delay_text[AUTO_LOCK_DELAY_COUNT] = { +static const char* const auto_lock_delay_text[AUTO_LOCK_DELAY_COUNT] = { "OFF", "10s", "15s", @@ -24,21 +25,36 @@ const char* const auto_lock_delay_text[AUTO_LOCK_DELAY_COUNT] = { "5min", "10min", }; -const uint32_t auto_lock_delay_value[AUTO_LOCK_DELAY_COUNT] = +static const uint32_t auto_lock_delay_value[AUTO_LOCK_DELAY_COUNT] = {0, 10000, 15000, 30000, 60000, 90000, 120000, 300000, 600000}; +#define CLOCK_ENABLE_COUNT 2 +const char* const clock_enable_text[CLOCK_ENABLE_COUNT] = { + "OFF", + "ON", +}; + +const uint32_t clock_enable_value[CLOCK_ENABLE_COUNT] = {0, 1}; + static void desktop_settings_scene_start_var_list_enter_callback(void* context, uint32_t index) { DesktopSettingsApp* app = context; view_dispatcher_send_custom_event(app->view_dispatcher, index); } +static void desktop_settings_scene_start_clock_enable_changed(VariableItem* item) { + DesktopSettingsApp* app = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, clock_enable_text[index]); + app->settings.display_clock = index; +} + static void desktop_settings_scene_start_auto_lock_delay_changed(VariableItem* item) { DesktopSettingsApp* app = variable_item_get_context(item); uint8_t index = variable_item_get_current_value_index(item); variable_item_set_current_value_text(item, auto_lock_delay_text[index]); - app->desktop->settings.auto_lock_delay_ms = auto_lock_delay_value[index]; - app->save_settings = true; + app->settings.auto_lock_delay_ms = auto_lock_delay_value[index]; } static void desktop_settings_scene_start_auto_lock_pin_changed(VariableItem* item) { @@ -46,8 +62,7 @@ static void desktop_settings_scene_start_auto_lock_pin_changed(VariableItem* ite uint8_t value = variable_item_get_current_value_index(item); variable_item_set_current_value_text(item, value ? "ON" : "OFF"); - app->desktop->settings.auto_lock_with_pin = value; - app->save_settings = true; + app->settings.auto_lock_with_pin = value; } void desktop_settings_scene_start_on_enter(void* context) { @@ -57,12 +72,12 @@ void desktop_settings_scene_start_on_enter(void* context) { VariableItem* item; uint8_t value_index; + variable_item_list_add(variable_item_list, "PIN Setup", 1, NULL, NULL); + variable_item_list_add(variable_item_list, "Keybinds Setup", 1, NULL, NULL); variable_item_list_add(variable_item_list, "Reset Keybinds to Default", 1, NULL, NULL); - variable_item_list_add(variable_item_list, "PIN Setup", 1, NULL, NULL); - item = variable_item_list_add( variable_item_list, "Auto Lock Time", @@ -71,7 +86,7 @@ void desktop_settings_scene_start_on_enter(void* context) { app); value_index = value_index_uint32( - app->desktop->settings.auto_lock_delay_ms, auto_lock_delay_value, AUTO_LOCK_DELAY_COUNT); + app->settings.auto_lock_delay_ms, auto_lock_delay_value, AUTO_LOCK_DELAY_COUNT); variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text(item, auto_lock_delay_text[value_index]); @@ -82,9 +97,20 @@ void desktop_settings_scene_start_on_enter(void* context) { desktop_settings_scene_start_auto_lock_pin_changed, app); - variable_item_set_current_value_index(item, app->desktop->settings.auto_lock_with_pin); - variable_item_set_current_value_text( - item, app->desktop->settings.auto_lock_with_pin ? "ON" : "OFF"); + variable_item_set_current_value_index(item, app->settings.auto_lock_with_pin); + variable_item_set_current_value_text(item, app->settings.auto_lock_with_pin ? "ON" : "OFF"); + + item = variable_item_list_add( + variable_item_list, + "Show Clock", + CLOCK_ENABLE_COUNT, + desktop_settings_scene_start_clock_enable_changed, // + app); + + value_index = + value_index_uint32(app->settings.display_clock, clock_enable_value, CLOCK_ENABLE_COUNT); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, clock_enable_text[value_index]); variable_item_list_set_enter_callback( variable_item_list, desktop_settings_scene_start_var_list_enter_callback, app); @@ -98,23 +124,28 @@ bool desktop_settings_scene_start_on_event(void* context, SceneManagerEvent even if(event.type == SceneManagerEventTypeCustom) { switch(event.event) { - case VarItemListIndexKeybinds: + case DesktopSettingsPinSetup: + scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinMenu); + break; + + case DesktopSettingsKeybindSetup: scene_manager_set_scene_state( app->scene_manager, DesktopSettingsAppSceneKeybindsType, 0); scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneKeybindsType); consumed = true; break; - case VarItemListIndexResetKeybinds: + + case DesktopSettingsResetKeybinds: scene_manager_set_scene_state( app->scene_manager, DesktopSettingsAppSceneKeybindsType, 0); scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneKeybindsReset); consumed = true; break; - case VarItemListIndexPinSetup: - scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinMenu); - consumed = true; + + default: break; } + consumed = true; } return consumed; } diff --git a/applications/settings/desktop_settings/views/desktop_view_pin_input.c b/applications/settings/desktop_settings/views/desktop_view_pin_input.c deleted file mode 100644 index 56ed98f53..000000000 --- a/applications/settings/desktop_settings/views/desktop_view_pin_input.c +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/applications/settings/dolphin_passport/mock_imports/mock_dolphin_state.c b/applications/settings/dolphin_passport/mock_imports/mock_dolphin_state.c new file mode 100644 index 000000000..732ccc18a --- /dev/null +++ b/applications/settings/dolphin_passport/mock_imports/mock_dolphin_state.c @@ -0,0 +1,7 @@ +// Since settings app is external, it cannot access firmware functions +// For simple utils like this, easier to include C code in app rather than exposing to API +// Instead of copying the file, can (ab)use the preprocessor to insert the source code here +// Then, we still use the Header from original code as if nothing happened + +// DOLPHIN_LEVELS, DOLPHIN_LEVEL_COUNT, dolphin_state_xp_to_levelup(), dolphin_state_xp_above_last_levelup() +#include diff --git a/applications/settings/expansion_settings_app/expansion_settings_app.c b/applications/settings/expansion_settings_app/expansion_settings_app.c index fe0e3ca2c..639f7f23d 100644 --- a/applications/settings/expansion_settings_app/expansion_settings_app.c +++ b/applications/settings/expansion_settings_app/expansion_settings_app.c @@ -10,7 +10,7 @@ static void expansion_settings_app_uart_changed(VariableItem* item) { ExpansionSettingsApp* app = variable_item_get_context(item); const uint8_t index = variable_item_get_current_value_index(item); variable_item_set_current_value_text(item, expansion_uart_text[index]); - app->settings->uart_index = index; + app->settings.uart_index = index; if(index < FuriHalSerialIdMax) { expansion_set_listen_serial(app->expansion, index); @@ -27,12 +27,12 @@ static uint32_t expansion_settings_app_exit(void* context) { static ExpansionSettingsApp* expansion_settings_app_alloc(void) { ExpansionSettingsApp* app = malloc(sizeof(ExpansionSettingsApp)); + expansion_settings_load(&app->settings); + app->gui = furi_record_open(RECORD_GUI); app->expansion = furi_record_open(RECORD_EXPANSION); - app->settings = expansion_get_settings(app->expansion); app->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_enable_queue(app->view_dispatcher); view_dispatcher_set_event_callback_context(app->view_dispatcher, app); view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); @@ -48,7 +48,7 @@ static ExpansionSettingsApp* expansion_settings_app_alloc(void) { COUNT_OF(expansion_uart_text), expansion_settings_app_uart_changed, app); - value_index = app->settings->uart_index; + value_index = app->settings.uart_index; variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text(item, expansion_uart_text[value_index]); @@ -67,7 +67,7 @@ static ExpansionSettingsApp* expansion_settings_app_alloc(void) { static void expansion_settings_app_free(ExpansionSettingsApp* app) { furi_assert(app); - expansion_settings_save(app->settings); + expansion_settings_save(&app->settings); view_dispatcher_remove_view(app->view_dispatcher, ExpansionSettingsViewVarItemList); variable_item_list_free(app->var_item_list); diff --git a/applications/settings/expansion_settings_app/expansion_settings_app.h b/applications/settings/expansion_settings_app/expansion_settings_app.h index a404f9c1a..a43bf853f 100644 --- a/applications/settings/expansion_settings_app/expansion_settings_app.h +++ b/applications/settings/expansion_settings_app/expansion_settings_app.h @@ -8,7 +8,6 @@ #include #include -#include #include typedef struct { @@ -16,7 +15,7 @@ typedef struct { ViewDispatcher* view_dispatcher; VariableItemList* var_item_list; Expansion* expansion; - ExpansionSettings* settings; + ExpansionSettings settings; } ExpansionSettingsApp; typedef enum { diff --git a/applications/settings/expansion_settings_app/mock_imports/mock_expansion_settings.c b/applications/settings/expansion_settings_app/mock_imports/mock_expansion_settings.c new file mode 100644 index 000000000..2a2a68768 --- /dev/null +++ b/applications/settings/expansion_settings_app/mock_imports/mock_expansion_settings.c @@ -0,0 +1,7 @@ +// Since settings app is external, it cannot access firmware functions +// For simple utils like this, easier to include C code in app rather than exposing to API +// Instead of copying the file, can (ab)use the preprocessor to insert the source code here +// Then, we still use the Header from original code as if nothing happened + +// expansion_settings_load(), expansion_settings_save() +#include diff --git a/applications/settings/notification_settings/mock_imports/mock_notification_app.c b/applications/settings/notification_settings/mock_imports/mock_notification_app.c new file mode 100644 index 000000000..6f48f14da --- /dev/null +++ b/applications/settings/notification_settings/mock_imports/mock_notification_app.c @@ -0,0 +1,7 @@ +// Since settings app is external, it cannot access firmware functions +// For simple utils like this, easier to include C code in app rather than exposing to API +// Instead of copying the file, can (ab)use the preprocessor to insert the source code here +// Then, we still use the Header from original code as if nothing happened + +// notification_message_save_settings() +#include diff --git a/applications/settings/notification_settings/notification_settings_app.c b/applications/settings/notification_settings/notification_settings_app.c index 56e63d876..2462b32bd 100644 --- a/applications/settings/notification_settings/notification_settings_app.c +++ b/applications/settings/notification_settings/notification_settings_app.c @@ -193,7 +193,7 @@ static NotificationAppSettings* alloc_settings(void) { variable_item_set_current_value_text(item, contrast_text[value_index]); item = variable_item_list_add( - app->variable_item_list, "LCD Brightness", BACKLIGHT_COUNT, backlight_changed, app); + app->variable_item_list, "LCD Backlight", BACKLIGHT_COUNT, backlight_changed, app); value_index = value_index_float( app->notification->settings.display_brightness, backlight_value, BACKLIGHT_COUNT); variable_item_set_current_value_index(item, value_index); @@ -242,7 +242,6 @@ static NotificationAppSettings* alloc_settings(void) { } app->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_enable_queue(app->view_dispatcher); view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); view_dispatcher_add_view(app->view_dispatcher, 0, view); view_dispatcher_switch_to_view(app->view_dispatcher, 0); diff --git a/applications/settings/power_settings_app/about.c b/applications/settings/power_settings_app/about.c deleted file mode 100644 index d33248c4f..000000000 --- a/applications/settings/power_settings_app/about.c +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/applications/settings/power_settings_app/mock_imports/mock_about.c b/applications/settings/power_settings_app/mock_imports/mock_about.c new file mode 100644 index 000000000..6c0d74a22 --- /dev/null +++ b/applications/settings/power_settings_app/mock_imports/mock_about.c @@ -0,0 +1,7 @@ +// Since settings app is external, it cannot access firmware functions +// For simple utils like this, easier to include C code in app rather than exposing to API +// Instead of copying the file, can (ab)use the preprocessor to insert the source code here +// Then, we still use the Header from original code as if nothing happened + +// about_settings_app() +#include diff --git a/applications/settings/power_settings_app/mock_imports/mock_power_api.c b/applications/settings/power_settings_app/mock_imports/mock_power_api.c new file mode 100644 index 000000000..ef69fc9ca --- /dev/null +++ b/applications/settings/power_settings_app/mock_imports/mock_power_api.c @@ -0,0 +1,7 @@ +// Since settings app is external, it cannot access firmware functions +// For simple utils like this, easier to include C code in app rather than exposing to API +// Instead of copying the file, can (ab)use the preprocessor to insert the source code here +// Then, we still use the Header from original code as if nothing happened + +// power_get_settings(), power_set_settings() +#include diff --git a/applications/settings/power_settings_app/power_settings_app.c b/applications/settings/power_settings_app/power_settings_app.c index 1f87b4959..834c03476 100644 --- a/applications/settings/power_settings_app/power_settings_app.c +++ b/applications/settings/power_settings_app/power_settings_app.c @@ -28,13 +28,9 @@ PowerSettingsApp* power_settings_app_alloc(uint32_t first_scene, ViewDispatcherT app->gui = furi_record_open(RECORD_GUI); app->power = furi_record_open(RECORD_POWER); - //PubSub - app->settings_events = power_get_settings_events_pubsub(app->power); - // View dispatcher app->view_dispatcher = view_dispatcher_alloc(); app->scene_manager = scene_manager_alloc(&power_settings_scene_handlers, app); - view_dispatcher_enable_queue(app->view_dispatcher); view_dispatcher_set_event_callback_context(app->view_dispatcher, app); view_dispatcher_set_custom_event_callback( app->view_dispatcher, power_settings_custom_event_callback); @@ -65,6 +61,8 @@ PowerSettingsApp* power_settings_app_alloc(uint32_t first_scene, ViewDispatcherT PowerSettingsAppViewVariableItemList, variable_item_list_get_view(app->variable_item_list)); + power_get_settings(app->power, &app->settings); + // Set first scene scene_manager_next_scene(app->scene_manager, first_scene); return app; @@ -72,6 +70,7 @@ PowerSettingsApp* power_settings_app_alloc(uint32_t first_scene, ViewDispatcherT void power_settings_app_free(PowerSettingsApp* app) { furi_assert(app); + power_set_settings(app->power, &app->settings); // Views view_dispatcher_remove_view(app->view_dispatcher, PowerSettingsAppViewBatteryInfo); battery_info_free(app->battery_info); diff --git a/applications/settings/power_settings_app/power_settings_app.h b/applications/settings/power_settings_app/power_settings_app.h index 65d4fd20c..0b8425a7b 100644 --- a/applications/settings/power_settings_app/power_settings_app.h +++ b/applications/settings/power_settings_app/power_settings_app.h @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -13,21 +14,21 @@ #include #include -#include #include "scenes/power_settings_scene.h" typedef struct { + PowerSettings settings; + Power* power; Gui* gui; SceneManager* scene_manager; ViewDispatcher* view_dispatcher; BatteryInfo* battery_info; Submenu* submenu; + VariableItemList* variable_item_list; DialogEx* dialog; PowerInfo info; - VariableItemList* variable_item_list; - uint32_t shutdown_idle_delay_ms; - FuriPubSub* settings_events; + bool about_battery; } PowerSettingsApp; diff --git a/applications/settings/power_settings_app/scenes/power_settings_scene_config.h b/applications/settings/power_settings_app/scenes/power_settings_scene_config.h index 1b4436f14..f57071b9b 100644 --- a/applications/settings/power_settings_app/scenes/power_settings_scene_config.h +++ b/applications/settings/power_settings_app/scenes/power_settings_scene_config.h @@ -3,4 +3,3 @@ ADD_SCENE(power_settings, battery_info, BatteryInfo) ADD_SCENE(power_settings, reboot, Reboot) ADD_SCENE(power_settings, reboot_confirm, RebootConfirm) ADD_SCENE(power_settings, power_off, PowerOff) -ADD_SCENE(power_settings, shutdown_idle, ShutdownIdle) diff --git a/applications/settings/power_settings_app/scenes/power_settings_scene_reboot_confirm.c b/applications/settings/power_settings_app/scenes/power_settings_scene_reboot_confirm.c index 62e06de92..25e7b2bc4 100644 --- a/applications/settings/power_settings_app/scenes/power_settings_scene_reboot_confirm.c +++ b/applications/settings/power_settings_app/scenes/power_settings_scene_reboot_confirm.c @@ -49,10 +49,12 @@ bool power_settings_scene_reboot_confirm_on_event(void* context, SceneManagerEve if(event.event == DialogExResultLeft) { scene_manager_previous_scene(app->scene_manager); } else if(event.event == DialogExResultRight) { + Power* power = furi_record_open(RECORD_POWER); + if(reboot_type == RebootTypeDFU) { - power_reboot(PowerBootModeDfu); + power_reboot(power, PowerBootModeDfu); } else { - power_reboot(PowerBootModeNormal); + power_reboot(power, PowerBootModeNormal); } } consumed = true; diff --git a/applications/settings/power_settings_app/scenes/power_settings_scene_shutdown_idle.c b/applications/settings/power_settings_app/scenes/power_settings_scene_shutdown_idle.c deleted file mode 100644 index a04f9fdf2..000000000 --- a/applications/settings/power_settings_app/scenes/power_settings_scene_shutdown_idle.c +++ /dev/null @@ -1,68 +0,0 @@ -#include "../power_settings_app.h" -#include - -#define SHUTDOWN_IDLE_DELAY_COUNT 9 -#define SCENE_EVENT_SELECT_SHUTDOWN_IDLE_DELAY 0 - -const char* const shutdown_idle_delay_text[SHUTDOWN_IDLE_DELAY_COUNT] = - {"OFF", "15min", "30min", "1h", "2h", "6h", "12h", "24h", "48h"}; - -const uint32_t shutdown_idle_delay_value[SHUTDOWN_IDLE_DELAY_COUNT] = - {0, 900000, 1800000, 3600000, 7200000, 21600000, 43200000, 86400000, 172800000}; - -static void power_settings_scene_shutodwn_idle_callback(void* context, uint32_t index) { - PowerSettingsApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, index); -} - -static void power_settings_scene_start_shutdown_idle_delay_changed(VariableItem* item) { - PowerSettingsApp* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - - variable_item_set_current_value_text(item, shutdown_idle_delay_text[index]); - app->shutdown_idle_delay_ms = shutdown_idle_delay_value[index]; -} - -void power_settings_scene_shutdown_idle_on_enter(void* context) { - PowerSettingsApp* app = context; - LOAD_POWER_SETTINGS(&app->shutdown_idle_delay_ms); - VariableItemList* variable_item_list = app->variable_item_list; - VariableItem* item; - uint8_t value_index; - - item = variable_item_list_add( - variable_item_list, - "Set Time", - SHUTDOWN_IDLE_DELAY_COUNT, - power_settings_scene_start_shutdown_idle_delay_changed, - app); - - variable_item_list_set_enter_callback( - variable_item_list, power_settings_scene_shutodwn_idle_callback, app); - - value_index = value_index_uint32( - app->shutdown_idle_delay_ms, shutdown_idle_delay_value, SHUTDOWN_IDLE_DELAY_COUNT); - variable_item_set_current_value_index(item, value_index); - variable_item_set_current_value_text(item, shutdown_idle_delay_text[value_index]); - - view_dispatcher_switch_to_view(app->view_dispatcher, PowerSettingsAppViewVariableItemList); -} - -bool power_settings_scene_shutdown_idle_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SCENE_EVENT_SELECT_SHUTDOWN_IDLE_DELAY) { - consumed = true; - } - } - return consumed; -} - -void power_settings_scene_shutdown_idle_on_exit(void* context) { - PowerSettingsApp* app = context; - SAVE_POWER_SETTINGS(&app->shutdown_idle_delay_ms); - furi_pubsub_publish(app->settings_events, &app->shutdown_idle_delay_ms); - variable_item_list_reset(app->variable_item_list); -} diff --git a/applications/settings/power_settings_app/scenes/power_settings_scene_start.c b/applications/settings/power_settings_app/scenes/power_settings_scene_start.c index 47c5b85c3..22c61dd9c 100644 --- a/applications/settings/power_settings_app/scenes/power_settings_scene_start.c +++ b/applications/settings/power_settings_app/scenes/power_settings_scene_start.c @@ -1,5 +1,7 @@ #include "../power_settings_app.h" +#include + enum PowerSettingsSubmenuIndex { PowerSettingsSubmenuIndexBatteryInfo, PowerSettingsSubmenuIndexReboot, @@ -7,6 +9,29 @@ enum PowerSettingsSubmenuIndex { PowerSettingsSubmenuShutdownIdle }; +#define SHUTDOWN_IDLE_DELAY_COUNT 9 +const char* const shutdown_idle_delay_text[SHUTDOWN_IDLE_DELAY_COUNT] = { + "OFF", + "15m", + "30m", + "1h", + "2h", + "6h", + "12h", + "24h", + "48h", +}; +const uint32_t shutdown_idle_delay_value[SHUTDOWN_IDLE_DELAY_COUNT] = + {0, 900000, 1800000, 3600000, 7200000, 21600000, 43200000, 86400000, 172800000}; + +static void power_settings_scene_start_auto_lock_delay_changed(VariableItem* item) { + PowerSettingsApp* app = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, shutdown_idle_delay_text[index]); + app->settings.shutdown_idle_delay_ms = shutdown_idle_delay_value[index]; +} + static void power_settings_scene_start_submenu_callback(void* context, uint32_t index) { furi_assert(context); PowerSettingsApp* app = context; @@ -15,36 +40,38 @@ static void power_settings_scene_start_submenu_callback(void* context, uint32_t void power_settings_scene_start_on_enter(void* context) { PowerSettingsApp* app = context; - Submenu* submenu = app->submenu; + VariableItemList* variable_item_list = app->variable_item_list; - submenu_add_item( - submenu, - "Battery Info", - PowerSettingsSubmenuIndexBatteryInfo, - power_settings_scene_start_submenu_callback, - app); - submenu_add_item( - submenu, - "Reboot", - PowerSettingsSubmenuIndexReboot, - power_settings_scene_start_submenu_callback, - app); - submenu_add_item( - submenu, - "Power OFF", - PowerSettingsSubmenuIndexOff, - power_settings_scene_start_submenu_callback, - app); - submenu_add_item( - submenu, + VariableItem* item; + uint8_t value_index; + + variable_item_list_add(variable_item_list, "Battery Info", 1, NULL, NULL); + + variable_item_list_add(variable_item_list, "Reboot", 1, NULL, NULL); + + variable_item_list_add(variable_item_list, "Power OFF", 1, NULL, NULL); + + item = variable_item_list_add( + variable_item_list, "Shutdown on Idle", - PowerSettingsSubmenuShutdownIdle, - power_settings_scene_start_submenu_callback, + SHUTDOWN_IDLE_DELAY_COUNT, + power_settings_scene_start_auto_lock_delay_changed, app); - submenu_set_selected_item( - submenu, scene_manager_get_scene_state(app->scene_manager, PowerSettingsAppSceneStart)); + value_index = value_index_uint32( + app->settings.shutdown_idle_delay_ms, + shutdown_idle_delay_value, + SHUTDOWN_IDLE_DELAY_COUNT); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, shutdown_idle_delay_text[value_index]); - view_dispatcher_switch_to_view(app->view_dispatcher, PowerSettingsAppViewSubmenu); + variable_item_list_set_selected_item( + variable_item_list, + scene_manager_get_scene_state(app->scene_manager, PowerSettingsAppSceneStart)); + + variable_item_list_set_enter_callback( + variable_item_list, power_settings_scene_start_submenu_callback, app); + + view_dispatcher_switch_to_view(app->view_dispatcher, PowerSettingsAppViewVariableItemList); } bool power_settings_scene_start_on_event(void* context, SceneManagerEvent event) { @@ -59,7 +86,6 @@ bool power_settings_scene_start_on_event(void* context, SceneManagerEvent event) } else if(event.event == PowerSettingsSubmenuIndexOff) { scene_manager_next_scene(app->scene_manager, PowerSettingsAppScenePowerOff); } else if(event.event == PowerSettingsSubmenuShutdownIdle) { - scene_manager_next_scene(app->scene_manager, PowerSettingsAppSceneShutdownIdle); } scene_manager_set_scene_state(app->scene_manager, PowerSettingsAppSceneStart, event.event); consumed = true; diff --git a/applications/settings/storage_settings/scenes/storage_settings_scene_factory_reset.c b/applications/settings/storage_settings/scenes/storage_settings_scene_factory_reset.c index 2d977176a..0f8e1aa96 100644 --- a/applications/settings/storage_settings/scenes/storage_settings_scene_factory_reset.c +++ b/applications/settings/storage_settings/scenes/storage_settings_scene_factory_reset.c @@ -65,7 +65,9 @@ bool storage_settings_scene_factory_reset_on_event(void* context, SceneManagerEv } else { furi_hal_rtc_reset_registers(); furi_hal_rtc_set_flag(FuriHalRtcFlagStorageFormatInternal); - power_reboot(PowerBootModeNormal); + + Power* power = furi_record_open(RECORD_POWER); + power_reboot(power, PowerBootModeNormal); } consumed = true; diff --git a/applications/settings/storage_settings/scenes/storage_settings_scene_formatting.c b/applications/settings/storage_settings/scenes/storage_settings_scene_formatting.c index 700391c3b..d1652fa20 100644 --- a/applications/settings/storage_settings/scenes/storage_settings_scene_formatting.c +++ b/applications/settings/storage_settings/scenes/storage_settings_scene_formatting.c @@ -53,7 +53,8 @@ void storage_settings_scene_formatting_on_enter(void* context) { dialog_ex, storage_error_get_desc(error), 64, 32, AlignCenter, AlignCenter); } else { if(scene_manager_get_scene_state(app->scene_manager, StorageSettingsFormatting)) { - power_reboot(PowerBootModeNormal); + Power* power = furi_record_open(RECORD_POWER); + power_reboot(power, PowerBootModeNormal); } else { dialog_ex_set_icon(dialog_ex, 48, 6, &I_DolphinDone_80x58); dialog_ex_set_header(dialog_ex, "Formatted", 5, 10, AlignLeft, AlignTop); diff --git a/applications/settings/storage_settings/scenes/storage_settings_scene_internal_info.c b/applications/settings/storage_settings/scenes/storage_settings_scene_internal_info.c index b7620b6e8..87a7ac655 100644 --- a/applications/settings/storage_settings/scenes/storage_settings_scene_internal_info.c +++ b/applications/settings/storage_settings/scenes/storage_settings_scene_internal_info.c @@ -1,5 +1,6 @@ #include "../storage_settings.h" #include +#include static void storage_settings_scene_internal_info_dialog_callback(DialogExResult result, void* context) { @@ -27,10 +28,20 @@ void storage_settings_scene_internal_info_on_enter(void* context) { } else { furi_string_printf( app->text_string, - "Name: %s\nType: LittleFS\nTotal: %lu KiB\nFree: %lu KiB", + "Name: %s\nType: Virtual (/.int on SD)\nTotal: %lu KiB\nFree: %lu KiB\n", furi_hal_version_get_name_ptr() ? furi_hal_version_get_name_ptr() : "Unknown", (uint32_t)(total_space / 1024), (uint32_t)(free_space / 1024)); + + uint32_t free_flash = + furi_hal_flash_get_free_end_address() - furi_hal_flash_get_free_start_address(); + if(free_flash < 1024) { + furi_string_cat_printf(app->text_string, "Flash: %lu B free", free_flash); + } else { + furi_string_cat_printf( + app->text_string, "Flash: %.2f KiB free", (double)free_flash / 1024); + } + dialog_ex_set_text( dialog_ex, furi_string_get_cstr(app->text_string), 4, 4, AlignLeft, AlignTop); } diff --git a/applications/settings/storage_settings/storage_settings.c b/applications/settings/storage_settings/storage_settings.c index 82759a288..a6a7b26aa 100644 --- a/applications/settings/storage_settings/storage_settings.c +++ b/applications/settings/storage_settings/storage_settings.c @@ -23,7 +23,6 @@ static StorageSettings* storage_settings_alloc(void) { app->scene_manager = scene_manager_alloc(&storage_settings_scene_handlers, app); app->text_string = furi_string_alloc(); - view_dispatcher_enable_queue(app->view_dispatcher); view_dispatcher_set_event_callback_context(app->view_dispatcher, app); view_dispatcher_set_custom_event_callback( diff --git a/applications/settings/system/system_settings.c b/applications/settings/system/system_settings.c index cc96aa300..b853abd33 100644 --- a/applications/settings/system/system_settings.c +++ b/applications/settings/system/system_settings.c @@ -163,6 +163,21 @@ static void date_format_changed(VariableItem* item) { locale_set_date_format(date_format_value[index]); } +const char* const hand_mode[] = { + "Righty", + "Lefty", +}; + +static void hand_orient_changed(VariableItem* item) { + uint8_t index = variable_item_get_current_value_index(item); + variable_item_set_current_value_text(item, hand_mode[index]); + if(index) { + furi_hal_rtc_set_flag(FuriHalRtcFlagHandOrient); + } else { + furi_hal_rtc_reset_flag(FuriHalRtcFlagHandOrient); + } +} + const char* const sleep_method[] = { "Default", "Legacy", @@ -205,7 +220,6 @@ SystemSettings* system_settings_alloc(void) { app->gui = furi_record_open(RECORD_GUI); app->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_enable_queue(app->view_dispatcher); view_dispatcher_set_event_callback_context(app->view_dispatcher, app); view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); @@ -214,6 +228,12 @@ SystemSettings* system_settings_alloc(void) { uint8_t value_index; app->var_item_list = variable_item_list_alloc(); + item = variable_item_list_add( + app->var_item_list, "Hand Orient", COUNT_OF(hand_mode), hand_orient_changed, app); + value_index = furi_hal_rtc_is_flag_set(FuriHalRtcFlagHandOrient) ? 1 : 0; + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, hand_mode[value_index]); + item = variable_item_list_add( app->var_item_list, "Units", diff --git a/applications/system/application.fam b/applications/system/application.fam index 2e9663287..9b3bbcd84 100644 --- a/applications/system/application.fam +++ b/applications/system/application.fam @@ -4,7 +4,6 @@ App( apptype=FlipperAppType.METAPACKAGE, provides=[ "updater_app", - "storage_move_to_sd", "js_app", "js_app_start", "findmy_startup", diff --git a/applications/system/findmy/findmy.c b/applications/system/findmy/findmy.c index ba6735b64..24a27ced6 100644 --- a/applications/system/findmy/findmy.c +++ b/applications/system/findmy/findmy.c @@ -20,7 +20,6 @@ static FindMy* findmy_app_alloc() { app->dialogs = furi_record_open(RECORD_DIALOGS); app->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_enable_queue(app->view_dispatcher); app->scene_manager = scene_manager_alloc(&findmy_scene_handlers, app); diff --git a/applications/system/findmy/findmy_startup.c b/applications/system/findmy/findmy_startup.c index 0bbc2a832..b8344671d 100644 --- a/applications/system/findmy/findmy_startup.c +++ b/applications/system/findmy/findmy_startup.c @@ -1,17 +1,51 @@ #include "findmy_state.h" #include #include +#include +#include -void findmy_startup() { - if(!furi_hal_is_normal_boot()) return; +#define TAG "FindMyStartup" + +static int32_t findmy_startup_apply(void* context) { + UNUSED(context); + FURI_LOG_D(TAG, "Loading state"); // Wait for BT init and check core2 furi_record_open(RECORD_BT); furi_record_close(RECORD_BT); - if(!furi_hal_bt_is_gatt_gap_supported()) return; + if(!furi_hal_bt_is_gatt_gap_supported()) return 0; FindMyState state; if(findmy_state_load(&state)) { + FURI_LOG_D(TAG, "Activating beacon"); findmy_state_apply(&state); + } else { + FURI_LOG_D(TAG, "Beacon not active, bailing"); + } + + return 0; +} + +static void findmy_startup_mount_callback(const void* message, void* context) { + UNUSED(context); + const StorageEvent* event = message; + + if(event->type == StorageEventTypeCardMount) { + run_parallel(findmy_startup_apply, NULL, 2048); } } + +void findmy_startup() { + if(!furi_hal_is_normal_boot()) return; + + Storage* storage = furi_record_open(RECORD_STORAGE); + furi_pubsub_subscribe(storage_get_pubsub(storage), findmy_startup_mount_callback, NULL); + + if(storage_sd_status(storage) != FSE_OK) { + FURI_LOG_D(TAG, "SD Card not ready, skipping startup hook"); + } else { + findmy_startup_apply(NULL); + } + + furi_record_close(RECORD_STORAGE); +} diff --git a/applications/system/findmy/icons/text_10px.png b/applications/system/findmy/icons/text_10px.png index 8e8a6183d..cd38770f4 100644 Binary files a/applications/system/findmy/icons/text_10px.png and b/applications/system/findmy/icons/text_10px.png differ diff --git a/applications/system/findmy/location_icon.png b/applications/system/findmy/location_icon.png index 841787a2a..49e687c23 100644 Binary files a/applications/system/findmy/location_icon.png and b/applications/system/findmy/location_icon.png differ diff --git a/applications/system/hid_app/assets/Alt_17x10.png b/applications/system/hid_app/assets/Alt_17x10.png index 78529ca07..54c4557ba 100644 Binary files a/applications/system/hid_app/assets/Alt_17x10.png and b/applications/system/hid_app/assets/Alt_17x10.png differ diff --git a/applications/system/hid_app/assets/Alt_active_17x9.png b/applications/system/hid_app/assets/Alt_active_17x9.png index 46a21a2e8..bd1adf606 100755 Binary files a/applications/system/hid_app/assets/Alt_active_17x9.png and b/applications/system/hid_app/assets/Alt_active_17x9.png differ diff --git a/applications/system/hid_app/assets/Arr_dwn_7x9.png b/applications/system/hid_app/assets/Arr_dwn_7x9.png index d4034efc4..dc97d3abc 100644 Binary files a/applications/system/hid_app/assets/Arr_dwn_7x9.png and b/applications/system/hid_app/assets/Arr_dwn_7x9.png differ diff --git a/applications/system/hid_app/assets/Arr_up_7x9.png b/applications/system/hid_app/assets/Arr_up_7x9.png index 28b4236a2..4e199c7d0 100644 Binary files a/applications/system/hid_app/assets/Arr_up_7x9.png and b/applications/system/hid_app/assets/Arr_up_7x9.png differ diff --git a/applications/system/hid_app/assets/Ble_connected_15x15.png b/applications/system/hid_app/assets/Ble_connected_15x15.png index 64dab9b53..1301399da 100644 Binary files a/applications/system/hid_app/assets/Ble_connected_15x15.png and b/applications/system/hid_app/assets/Ble_connected_15x15.png differ diff --git a/applications/system/hid_app/assets/Ble_disconnected_15x15.png b/applications/system/hid_app/assets/Ble_disconnected_15x15.png index bd54646d8..f926ce212 100644 Binary files a/applications/system/hid_app/assets/Ble_disconnected_15x15.png and b/applications/system/hid_app/assets/Ble_disconnected_15x15.png differ diff --git a/applications/system/hid_app/assets/BrokenButton_15x15.png b/applications/system/hid_app/assets/BrokenButton_15x15.png index a627d16ff..0f4ac6b3c 100644 Binary files a/applications/system/hid_app/assets/BrokenButton_15x15.png and b/applications/system/hid_app/assets/BrokenButton_15x15.png differ diff --git a/applications/system/hid_app/assets/BtnBackV_9x9.png b/applications/system/hid_app/assets/BtnBackV_9x9.png index 6aff407a8..be2f9b0e6 100644 Binary files a/applications/system/hid_app/assets/BtnBackV_9x9.png and b/applications/system/hid_app/assets/BtnBackV_9x9.png differ diff --git a/applications/system/hid_app/assets/BtnFrameLeft_3x18.png b/applications/system/hid_app/assets/BtnFrameLeft_3x18.png index f39e89f8b..a25950086 100644 Binary files a/applications/system/hid_app/assets/BtnFrameLeft_3x18.png and b/applications/system/hid_app/assets/BtnFrameLeft_3x18.png differ diff --git a/applications/system/hid_app/assets/BtnFrameRight_2x18.png b/applications/system/hid_app/assets/BtnFrameRight_2x18.png index d6edbb713..eef742cc4 100644 Binary files a/applications/system/hid_app/assets/BtnFrameRight_2x18.png and b/applications/system/hid_app/assets/BtnFrameRight_2x18.png differ diff --git a/applications/system/hid_app/assets/BtnLeft_9x9.png b/applications/system/hid_app/assets/BtnLeft_9x9.png index 1082423ac..c1ac8a658 100644 Binary files a/applications/system/hid_app/assets/BtnLeft_9x9.png and b/applications/system/hid_app/assets/BtnLeft_9x9.png differ diff --git a/applications/system/hid_app/assets/ButtonDown_7x4.png b/applications/system/hid_app/assets/ButtonDown_7x4.png index 2954bb6a6..0cda838e0 100644 Binary files a/applications/system/hid_app/assets/ButtonDown_7x4.png and b/applications/system/hid_app/assets/ButtonDown_7x4.png differ diff --git a/applications/system/hid_app/assets/ButtonF10_5x8.png b/applications/system/hid_app/assets/ButtonF10_5x8.png index d1a7a04f0..a817cce36 100644 Binary files a/applications/system/hid_app/assets/ButtonF10_5x8.png and b/applications/system/hid_app/assets/ButtonF10_5x8.png differ diff --git a/applications/system/hid_app/assets/ButtonF11_5x8.png b/applications/system/hid_app/assets/ButtonF11_5x8.png index 7e177358e..9ebe40150 100644 Binary files a/applications/system/hid_app/assets/ButtonF11_5x8.png and b/applications/system/hid_app/assets/ButtonF11_5x8.png differ diff --git a/applications/system/hid_app/assets/ButtonF12_5x8.png b/applications/system/hid_app/assets/ButtonF12_5x8.png index 50d2a7dc6..a50b16ca3 100644 Binary files a/applications/system/hid_app/assets/ButtonF12_5x8.png and b/applications/system/hid_app/assets/ButtonF12_5x8.png differ diff --git a/applications/system/hid_app/assets/ButtonF1_5x8.png b/applications/system/hid_app/assets/ButtonF1_5x8.png index 7394d2710..53a30974b 100644 Binary files a/applications/system/hid_app/assets/ButtonF1_5x8.png and b/applications/system/hid_app/assets/ButtonF1_5x8.png differ diff --git a/applications/system/hid_app/assets/ButtonF2_5x8.png b/applications/system/hid_app/assets/ButtonF2_5x8.png index 9d922a385..df28654a5 100644 Binary files a/applications/system/hid_app/assets/ButtonF2_5x8.png and b/applications/system/hid_app/assets/ButtonF2_5x8.png differ diff --git a/applications/system/hid_app/assets/ButtonF3_5x8.png b/applications/system/hid_app/assets/ButtonF3_5x8.png index 95c2dd4f4..a36cd56b9 100644 Binary files a/applications/system/hid_app/assets/ButtonF3_5x8.png and b/applications/system/hid_app/assets/ButtonF3_5x8.png differ diff --git a/applications/system/hid_app/assets/ButtonF4_5x8.png b/applications/system/hid_app/assets/ButtonF4_5x8.png index 602466f4b..535195859 100644 Binary files a/applications/system/hid_app/assets/ButtonF4_5x8.png and b/applications/system/hid_app/assets/ButtonF4_5x8.png differ diff --git a/applications/system/hid_app/assets/ButtonF5_5x8.png b/applications/system/hid_app/assets/ButtonF5_5x8.png index d73b54052..918017f5a 100644 Binary files a/applications/system/hid_app/assets/ButtonF5_5x8.png and b/applications/system/hid_app/assets/ButtonF5_5x8.png differ diff --git a/applications/system/hid_app/assets/ButtonF6_5x8.png b/applications/system/hid_app/assets/ButtonF6_5x8.png index c50748257..1009799a5 100644 Binary files a/applications/system/hid_app/assets/ButtonF6_5x8.png and b/applications/system/hid_app/assets/ButtonF6_5x8.png differ diff --git a/applications/system/hid_app/assets/ButtonF7_5x8.png b/applications/system/hid_app/assets/ButtonF7_5x8.png index 396c98f51..a6c44ddd8 100644 Binary files a/applications/system/hid_app/assets/ButtonF7_5x8.png and b/applications/system/hid_app/assets/ButtonF7_5x8.png differ diff --git a/applications/system/hid_app/assets/ButtonF8_5x8.png b/applications/system/hid_app/assets/ButtonF8_5x8.png index 6304d7fb8..a789a0f36 100644 Binary files a/applications/system/hid_app/assets/ButtonF8_5x8.png and b/applications/system/hid_app/assets/ButtonF8_5x8.png differ diff --git a/applications/system/hid_app/assets/ButtonF9_5x8.png b/applications/system/hid_app/assets/ButtonF9_5x8.png index 148e69580..222b2e151 100644 Binary files a/applications/system/hid_app/assets/ButtonF9_5x8.png and b/applications/system/hid_app/assets/ButtonF9_5x8.png differ diff --git a/applications/system/hid_app/assets/ButtonLeft_4x7.png b/applications/system/hid_app/assets/ButtonLeft_4x7.png index 0b4655d43..7c43f3b04 100644 Binary files a/applications/system/hid_app/assets/ButtonLeft_4x7.png and b/applications/system/hid_app/assets/ButtonLeft_4x7.png differ diff --git a/applications/system/hid_app/assets/ButtonRight_4x7.png b/applications/system/hid_app/assets/ButtonRight_4x7.png index 8e1c74c1c..31de21c0e 100644 Binary files a/applications/system/hid_app/assets/ButtonRight_4x7.png and b/applications/system/hid_app/assets/ButtonRight_4x7.png differ diff --git a/applications/system/hid_app/assets/ButtonUp_7x4.png b/applications/system/hid_app/assets/ButtonUp_7x4.png index 1be79328b..48d0f9f01 100644 Binary files a/applications/system/hid_app/assets/ButtonUp_7x4.png and b/applications/system/hid_app/assets/ButtonUp_7x4.png differ diff --git a/applications/system/hid_app/assets/Button_18x18.png b/applications/system/hid_app/assets/Button_18x18.png index 30a5b4fab..2334dd8be 100644 Binary files a/applications/system/hid_app/assets/Button_18x18.png and b/applications/system/hid_app/assets/Button_18x18.png differ diff --git a/applications/system/hid_app/assets/Cmd_17x10.png b/applications/system/hid_app/assets/Cmd_17x10.png index b29da07b7..68b3be606 100644 Binary files a/applications/system/hid_app/assets/Cmd_17x10.png and b/applications/system/hid_app/assets/Cmd_17x10.png differ diff --git a/applications/system/hid_app/assets/Cmd_active_17x9.png b/applications/system/hid_app/assets/Cmd_active_17x9.png index 9d31b4eb3..9f9cdea99 100755 Binary files a/applications/system/hid_app/assets/Cmd_active_17x9.png and b/applications/system/hid_app/assets/Cmd_active_17x9.png differ diff --git a/applications/system/hid_app/assets/Ctrl_17x10.png b/applications/system/hid_app/assets/Ctrl_17x10.png index 05be3292e..c70dd2c16 100644 Binary files a/applications/system/hid_app/assets/Ctrl_17x10.png and b/applications/system/hid_app/assets/Ctrl_17x10.png differ diff --git a/applications/system/hid_app/assets/Ctrl_active_17x9.png b/applications/system/hid_app/assets/Ctrl_active_17x9.png index 6fade6dd7..c16df04ee 100755 Binary files a/applications/system/hid_app/assets/Ctrl_active_17x9.png and b/applications/system/hid_app/assets/Ctrl_active_17x9.png differ diff --git a/applications/system/hid_app/assets/Del_17x10.png b/applications/system/hid_app/assets/Del_17x10.png index 95cbf7d5b..3fd55e92f 100644 Binary files a/applications/system/hid_app/assets/Del_17x10.png and b/applications/system/hid_app/assets/Del_17x10.png differ diff --git a/applications/system/hid_app/assets/DolphinDone_80x58.png b/applications/system/hid_app/assets/DolphinDone_80x58.png index 594d62d52..881aaa8d2 100644 Binary files a/applications/system/hid_app/assets/DolphinDone_80x58.png and b/applications/system/hid_app/assets/DolphinDone_80x58.png differ diff --git a/applications/system/hid_app/assets/Enter_11x7.png b/applications/system/hid_app/assets/Enter_11x7.png index d41b8feff..1b07df2cf 100755 Binary files a/applications/system/hid_app/assets/Enter_11x7.png and b/applications/system/hid_app/assets/Enter_11x7.png differ diff --git a/applications/system/hid_app/assets/Esc_17x10.png b/applications/system/hid_app/assets/Esc_17x10.png index 83a6f225f..bd7e3cb96 100644 Binary files a/applications/system/hid_app/assets/Esc_17x10.png and b/applications/system/hid_app/assets/Esc_17x10.png differ diff --git a/applications/system/hid_app/assets/Hand_8x10.png b/applications/system/hid_app/assets/Hand_8x10.png index 8defeed4d..b48d36479 100644 Binary files a/applications/system/hid_app/assets/Hand_8x10.png and b/applications/system/hid_app/assets/Hand_8x10.png differ diff --git a/applications/system/hid_app/assets/Help_exit_64x9.png b/applications/system/hid_app/assets/Help_exit_64x9.png index 7f40db387..72f5c0d30 100644 Binary files a/applications/system/hid_app/assets/Help_exit_64x9.png and b/applications/system/hid_app/assets/Help_exit_64x9.png differ diff --git a/applications/system/hid_app/assets/Help_top_64x17.png b/applications/system/hid_app/assets/Help_top_64x17.png index ecc0e6647..4717189f6 100644 Binary files a/applications/system/hid_app/assets/Help_top_64x17.png and b/applications/system/hid_app/assets/Help_top_64x17.png differ diff --git a/applications/system/hid_app/assets/Hold_15x5.png b/applications/system/hid_app/assets/Hold_15x5.png index 102d0bd7a..577bbe78c 100644 Binary files a/applications/system/hid_app/assets/Hold_15x5.png and b/applications/system/hid_app/assets/Hold_15x5.png differ diff --git a/applications/system/hid_app/assets/Left_mouse_icon_9x9.png b/applications/system/hid_app/assets/Left_mouse_icon_9x9.png index c533d8572..5bd2d395f 100644 Binary files a/applications/system/hid_app/assets/Left_mouse_icon_9x9.png and b/applications/system/hid_app/assets/Left_mouse_icon_9x9.png differ diff --git a/applications/system/hid_app/assets/Like_def_11x9.png b/applications/system/hid_app/assets/Like_def_11x9.png index 555bea3d4..61eddb9ed 100644 Binary files a/applications/system/hid_app/assets/Like_def_11x9.png and b/applications/system/hid_app/assets/Like_def_11x9.png differ diff --git a/applications/system/hid_app/assets/Mic_7x11.png b/applications/system/hid_app/assets/Mic_7x11.png index 49223394b..dc2e1a529 100644 Binary files a/applications/system/hid_app/assets/Mic_7x11.png and b/applications/system/hid_app/assets/Mic_7x11.png differ diff --git a/applications/system/hid_app/assets/MicrophoneCrossed_16x16.png b/applications/system/hid_app/assets/MicrophoneCrossed_16x16.png index 0e91d2f86..e50a99d71 100644 Binary files a/applications/system/hid_app/assets/MicrophoneCrossed_16x16.png and b/applications/system/hid_app/assets/MicrophoneCrossed_16x16.png differ diff --git a/applications/system/hid_app/assets/MicrophonePressedBtn_16x16.png b/applications/system/hid_app/assets/MicrophonePressedBtn_16x16.png index 911fe1b22..df08e65f5 100644 Binary files a/applications/system/hid_app/assets/MicrophonePressedBtn_16x16.png and b/applications/system/hid_app/assets/MicrophonePressedBtn_16x16.png differ diff --git a/applications/system/hid_app/assets/MicrophonePressedCrossedBtn_16x16.png b/applications/system/hid_app/assets/MicrophonePressedCrossedBtn_16x16.png index 1c485a85b..256f3ef13 100644 Binary files a/applications/system/hid_app/assets/MicrophonePressedCrossedBtn_16x16.png and b/applications/system/hid_app/assets/MicrophonePressedCrossedBtn_16x16.png differ diff --git a/applications/system/hid_app/assets/Ok_btn_9x9.png b/applications/system/hid_app/assets/Ok_btn_9x9.png index 9a1539da2..ceff4e8a8 100644 Binary files a/applications/system/hid_app/assets/Ok_btn_9x9.png and b/applications/system/hid_app/assets/Ok_btn_9x9.png differ diff --git a/applications/system/hid_app/assets/OutCircles_70x51.png b/applications/system/hid_app/assets/OutCircles_70x51.png index f34d2687a..ba90c328f 100644 Binary files a/applications/system/hid_app/assets/OutCircles_70x51.png and b/applications/system/hid_app/assets/OutCircles_70x51.png differ diff --git a/applications/system/hid_app/assets/Pause_icon_9x9.png b/applications/system/hid_app/assets/Pause_icon_9x9.png index fe16dc03e..3afb7711d 100644 Binary files a/applications/system/hid_app/assets/Pause_icon_9x9.png and b/applications/system/hid_app/assets/Pause_icon_9x9.png differ diff --git a/applications/system/hid_app/assets/Pin_arrow_down_7x9.png b/applications/system/hid_app/assets/Pin_arrow_down_7x9.png index 9687397af..dc97d3abc 100644 Binary files a/applications/system/hid_app/assets/Pin_arrow_down_7x9.png and b/applications/system/hid_app/assets/Pin_arrow_down_7x9.png differ diff --git a/applications/system/hid_app/assets/Pin_arrow_left_9x7.png b/applications/system/hid_app/assets/Pin_arrow_left_9x7.png index fb4ded78f..9b6ccb51f 100644 Binary files a/applications/system/hid_app/assets/Pin_arrow_left_9x7.png and b/applications/system/hid_app/assets/Pin_arrow_left_9x7.png differ diff --git a/applications/system/hid_app/assets/Pin_arrow_right_9x7.png b/applications/system/hid_app/assets/Pin_arrow_right_9x7.png index 97648d176..b79bca2e3 100644 Binary files a/applications/system/hid_app/assets/Pin_arrow_right_9x7.png and b/applications/system/hid_app/assets/Pin_arrow_right_9x7.png differ diff --git a/applications/system/hid_app/assets/Pin_arrow_up_7x9.png b/applications/system/hid_app/assets/Pin_arrow_up_7x9.png index a91a6fd5e..4e199c7d0 100644 Binary files a/applications/system/hid_app/assets/Pin_arrow_up_7x9.png and b/applications/system/hid_app/assets/Pin_arrow_up_7x9.png differ diff --git a/applications/system/hid_app/assets/Pin_back_arrow_10x10.png b/applications/system/hid_app/assets/Pin_back_arrow_10x10.png index e7510fd5d..1ec8de77a 100644 Binary files a/applications/system/hid_app/assets/Pin_back_arrow_10x10.png and b/applications/system/hid_app/assets/Pin_back_arrow_10x10.png differ diff --git a/applications/system/hid_app/assets/Pin_back_arrow_10x8.png b/applications/system/hid_app/assets/Pin_back_arrow_10x8.png index 3bafabd14..64b25db5a 100644 Binary files a/applications/system/hid_app/assets/Pin_back_arrow_10x8.png and b/applications/system/hid_app/assets/Pin_back_arrow_10x8.png differ diff --git a/applications/system/hid_app/assets/Pressed_Button_13x13.png b/applications/system/hid_app/assets/Pressed_Button_13x13.png index 823926b84..d0e2c3a37 100644 Binary files a/applications/system/hid_app/assets/Pressed_Button_13x13.png and b/applications/system/hid_app/assets/Pressed_Button_13x13.png differ diff --git a/applications/system/hid_app/assets/Pressed_Button_19x19.png b/applications/system/hid_app/assets/Pressed_Button_19x19.png index 42a7dbdcc..b48a4e071 100644 Binary files a/applications/system/hid_app/assets/Pressed_Button_19x19.png and b/applications/system/hid_app/assets/Pressed_Button_19x19.png differ diff --git a/applications/system/hid_app/assets/Return_10x7.png b/applications/system/hid_app/assets/Return_10x7.png index ffa1e9aca..ebf0a7777 100644 Binary files a/applications/system/hid_app/assets/Return_10x7.png and b/applications/system/hid_app/assets/Return_10x7.png differ diff --git a/applications/system/hid_app/assets/Right_mouse_icon_9x9.png b/applications/system/hid_app/assets/Right_mouse_icon_9x9.png index 446d7176c..1da29ee43 100644 Binary files a/applications/system/hid_app/assets/Right_mouse_icon_9x9.png and b/applications/system/hid_app/assets/Right_mouse_icon_9x9.png differ diff --git a/applications/system/hid_app/assets/RoundButtonUnpressed_16x16.png b/applications/system/hid_app/assets/RoundButtonUnpressed_16x16.png index e2fc85c19..e2af328d4 100644 Binary files a/applications/system/hid_app/assets/RoundButtonUnpressed_16x16.png and b/applications/system/hid_app/assets/RoundButtonUnpressed_16x16.png differ diff --git a/applications/system/hid_app/assets/S_DOWN_31x15.png b/applications/system/hid_app/assets/S_DOWN_31x15.png index eac667aa0..0f05105a6 100644 Binary files a/applications/system/hid_app/assets/S_DOWN_31x15.png and b/applications/system/hid_app/assets/S_DOWN_31x15.png differ diff --git a/applications/system/hid_app/assets/S_LEFT_15x31.png b/applications/system/hid_app/assets/S_LEFT_15x31.png index 13c9f51b4..07f0b63f9 100644 Binary files a/applications/system/hid_app/assets/S_LEFT_15x31.png and b/applications/system/hid_app/assets/S_LEFT_15x31.png differ diff --git a/applications/system/hid_app/assets/S_RIGHT_15x31.png b/applications/system/hid_app/assets/S_RIGHT_15x31.png index e0ba2afd1..7e913812f 100644 Binary files a/applications/system/hid_app/assets/S_RIGHT_15x31.png and b/applications/system/hid_app/assets/S_RIGHT_15x31.png differ diff --git a/applications/system/hid_app/assets/S_UP_31x15.png b/applications/system/hid_app/assets/S_UP_31x15.png index e55a03624..78a1d0d98 100644 Binary files a/applications/system/hid_app/assets/S_UP_31x15.png and b/applications/system/hid_app/assets/S_UP_31x15.png differ diff --git a/applications/system/hid_app/assets/Shift_active_7x9.png b/applications/system/hid_app/assets/Shift_active_7x9.png index 1ec9ce11e..1dbb762f9 100644 Binary files a/applications/system/hid_app/assets/Shift_active_7x9.png and b/applications/system/hid_app/assets/Shift_active_7x9.png differ diff --git a/applications/system/hid_app/assets/Shift_inactive_7x9.png b/applications/system/hid_app/assets/Shift_inactive_7x9.png index 1cd97076e..696e7e9ee 100644 Binary files a/applications/system/hid_app/assets/Shift_inactive_7x9.png and b/applications/system/hid_app/assets/Shift_inactive_7x9.png differ diff --git a/applications/system/hid_app/assets/Space_60x18.png b/applications/system/hid_app/assets/Space_60x18.png index e29f50ae9..7d2116ad5 100644 Binary files a/applications/system/hid_app/assets/Space_60x18.png and b/applications/system/hid_app/assets/Space_60x18.png differ diff --git a/applications/system/hid_app/assets/Space_65x18.png b/applications/system/hid_app/assets/Space_65x18.png index b60ae5097..eb417f674 100644 Binary files a/applications/system/hid_app/assets/Space_65x18.png and b/applications/system/hid_app/assets/Space_65x18.png differ diff --git a/applications/system/hid_app/assets/Tab_17x10.png b/applications/system/hid_app/assets/Tab_17x10.png index 4d8471483..0be2d938c 100644 Binary files a/applications/system/hid_app/assets/Tab_17x10.png and b/applications/system/hid_app/assets/Tab_17x10.png differ diff --git a/applications/system/hid_app/assets/Tab_19x12.png b/applications/system/hid_app/assets/Tab_19x12.png index 4dbde3bab..6748d1f49 100755 Binary files a/applications/system/hid_app/assets/Tab_19x12.png and b/applications/system/hid_app/assets/Tab_19x12.png differ diff --git a/applications/system/hid_app/assets/Voldwn_6x6.png b/applications/system/hid_app/assets/Voldwn_6x6.png index d7a82a2df..d6d7e286a 100644 Binary files a/applications/system/hid_app/assets/Voldwn_6x6.png and b/applications/system/hid_app/assets/Voldwn_6x6.png differ diff --git a/applications/system/hid_app/assets/Volup_8x6.png b/applications/system/hid_app/assets/Volup_8x6.png index 4b7ec66d6..66477bc7b 100644 Binary files a/applications/system/hid_app/assets/Volup_8x6.png and b/applications/system/hid_app/assets/Volup_8x6.png differ diff --git a/applications/system/hid_app/assets/apostrophe_button_9x11.png b/applications/system/hid_app/assets/apostrophe_button_9x11.png index 0f54f0e2b..a4b2cab8e 100644 Binary files a/applications/system/hid_app/assets/apostrophe_button_9x11.png and b/applications/system/hid_app/assets/apostrophe_button_9x11.png differ diff --git a/applications/system/hid_app/assets/backslash_button_9x11.png b/applications/system/hid_app/assets/backslash_button_9x11.png index 6cac74a57..e579e113e 100755 Binary files a/applications/system/hid_app/assets/backslash_button_9x11.png and b/applications/system/hid_app/assets/backslash_button_9x11.png differ diff --git a/applications/system/hid_app/assets/backspace_19x11.png b/applications/system/hid_app/assets/backspace_19x11.png index caf92807b..80e91c3c2 100755 Binary files a/applications/system/hid_app/assets/backspace_19x11.png and b/applications/system/hid_app/assets/backspace_19x11.png differ diff --git a/applications/system/hid_app/assets/backspace_hovered_9x11.png b/applications/system/hid_app/assets/backspace_hovered_9x11.png index 17cb1b740..a4acbf0db 100755 Binary files a/applications/system/hid_app/assets/backspace_hovered_9x11.png and b/applications/system/hid_app/assets/backspace_hovered_9x11.png differ diff --git a/applications/system/hid_app/assets/backtick_button_9x11.png b/applications/system/hid_app/assets/backtick_button_9x11.png index 1e5955a03..0d2b8942c 100755 Binary files a/applications/system/hid_app/assets/backtick_button_9x11.png and b/applications/system/hid_app/assets/backtick_button_9x11.png differ diff --git a/applications/system/hid_app/assets/brace_left_button_9x11.png b/applications/system/hid_app/assets/brace_left_button_9x11.png index a61db48f3..56eb69043 100755 Binary files a/applications/system/hid_app/assets/brace_left_button_9x11.png and b/applications/system/hid_app/assets/brace_left_button_9x11.png differ diff --git a/applications/system/hid_app/assets/brace_right_button_9x11.png b/applications/system/hid_app/assets/brace_right_button_9x11.png index bf6b927f1..8df2c19ce 100755 Binary files a/applications/system/hid_app/assets/brace_right_button_9x11.png and b/applications/system/hid_app/assets/brace_right_button_9x11.png differ diff --git a/applications/system/hid_app/assets/equals_button_9x11.png b/applications/system/hid_app/assets/equals_button_9x11.png index 8fe8afe34..4d3232af2 100755 Binary files a/applications/system/hid_app/assets/equals_button_9x11.png and b/applications/system/hid_app/assets/equals_button_9x11.png differ diff --git a/applications/system/hid_app/assets/for_help_27x5.png b/applications/system/hid_app/assets/for_help_27x5.png index 20bb30a08..13c307b46 100644 Binary files a/applications/system/hid_app/assets/for_help_27x5.png and b/applications/system/hid_app/assets/for_help_27x5.png differ diff --git a/applications/system/hid_app/assets/hash_button_9x11.png b/applications/system/hid_app/assets/hash_button_9x11.png index bddc7aace..0a3974f64 100755 Binary files a/applications/system/hid_app/assets/hash_button_9x11.png and b/applications/system/hid_app/assets/hash_button_9x11.png differ diff --git a/applications/system/hid_app/assets/percent_button_9x11.png b/applications/system/hid_app/assets/percent_button_9x11.png index ce12dcbf1..72190605b 100755 Binary files a/applications/system/hid_app/assets/percent_button_9x11.png and b/applications/system/hid_app/assets/percent_button_9x11.png differ diff --git a/applications/system/hid_app/assets/quote_button_9x11.png b/applications/system/hid_app/assets/quote_button_9x11.png index e96d29ddc..9fabcd26c 100755 Binary files a/applications/system/hid_app/assets/quote_button_9x11.png and b/applications/system/hid_app/assets/quote_button_9x11.png differ diff --git a/applications/system/hid_app/assets/slash_button_9x11.png b/applications/system/hid_app/assets/slash_button_9x11.png index 60871320f..b877b9106 100755 Binary files a/applications/system/hid_app/assets/slash_button_9x11.png and b/applications/system/hid_app/assets/slash_button_9x11.png differ diff --git a/applications/system/hid_app/assets/sq_bracket_left_button_9x11.png b/applications/system/hid_app/assets/sq_bracket_left_button_9x11.png index 0983db129..ea50cd657 100755 Binary files a/applications/system/hid_app/assets/sq_bracket_left_button_9x11.png and b/applications/system/hid_app/assets/sq_bracket_left_button_9x11.png differ diff --git a/applications/system/hid_app/assets/sq_bracket_right_button_9x11.png b/applications/system/hid_app/assets/sq_bracket_right_button_9x11.png index 48f9c77e4..bd18bbfad 100755 Binary files a/applications/system/hid_app/assets/sq_bracket_right_button_9x11.png and b/applications/system/hid_app/assets/sq_bracket_right_button_9x11.png differ diff --git a/applications/system/hid_app/assets/underscore_button_9x11.png b/applications/system/hid_app/assets/underscore_button_9x11.png index eb000cba5..7ab5cdbab 100755 Binary files a/applications/system/hid_app/assets/underscore_button_9x11.png and b/applications/system/hid_app/assets/underscore_button_9x11.png differ diff --git a/applications/system/hid_app/hid.c b/applications/system/hid_app/hid.c index 586d198a9..e297e0738 100644 --- a/applications/system/hid_app/hid.c +++ b/applications/system/hid_app/hid.c @@ -72,7 +72,6 @@ Hid* hid_alloc() { // View dispatcher app->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_enable_queue(app->view_dispatcher); view_dispatcher_set_event_callback_context(app->view_dispatcher, app); view_dispatcher_set_custom_event_callback(app->view_dispatcher, hid_custom_event_callback); view_dispatcher_set_navigation_event_callback(app->view_dispatcher, hid_back_event_callback); diff --git a/applications/system/hid_app/hid_ble_10px.png b/applications/system/hid_app/hid_ble_10px.png index d4d30afe0..27355f8db 100644 Binary files a/applications/system/hid_app/hid_ble_10px.png and b/applications/system/hid_app/hid_ble_10px.png differ diff --git a/applications/system/hid_app/hid_usb_10px.png b/applications/system/hid_app/hid_usb_10px.png index 415de7d23..0e78f2b78 100644 Binary files a/applications/system/hid_app/hid_usb_10px.png and b/applications/system/hid_app/hid_usb_10px.png differ diff --git a/applications/system/js_app/icon.png b/applications/system/js_app/icon.png index 77ac76337..48210a049 100644 Binary files a/applications/system/js_app/icon.png and b/applications/system/js_app/icon.png differ diff --git a/applications/system/js_app/js_app.c b/applications/system/js_app/js_app.c index 72ee4234a..f058d095b 100644 --- a/applications/system/js_app/js_app.c +++ b/applications/system/js_app/js_app.c @@ -69,7 +69,6 @@ static JsApp* js_app_alloc(void) { app->loading = loading_alloc(); app->gui = furi_record_open("gui"); - view_dispatcher_enable_queue(app->view_dispatcher); view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); view_dispatcher_add_view( app->view_dispatcher, JsAppViewLoading, loading_get_view(app->loading)); diff --git a/applications/system/js_app/modules/js_keyboard.c b/applications/system/js_app/modules/js_keyboard.c index 240d99787..c21fc1800 100644 --- a/applications/system/js_app/modules/js_keyboard.c +++ b/applications/system/js_app/modules/js_keyboard.c @@ -92,10 +92,9 @@ static void js_keyboard_text(struct mjs* mjs) { view_holder_set_back_callback(keyboard->view_holder, keyboard_exit, keyboard); view_holder_set_view(keyboard->view_holder, text_input_get_view(keyboard->text_input)); - view_holder_start(keyboard->view_holder); api_lock_wait_unlock(keyboard->lock); - view_holder_stop(keyboard->view_holder); + view_holder_set_view(keyboard->view_holder, NULL); view_holder_free(keyboard->view_holder); furi_record_close(RECORD_GUI); @@ -148,10 +147,9 @@ static void js_keyboard_byte(struct mjs* mjs) { view_holder_set_back_callback(keyboard->view_holder, keyboard_exit, keyboard); view_holder_set_view(keyboard->view_holder, byte_input_get_view(keyboard->byte_input)); - view_holder_start(keyboard->view_holder); api_lock_wait_unlock(keyboard->lock); - view_holder_stop(keyboard->view_holder); + view_holder_set_view(keyboard->view_holder, NULL); view_holder_free(keyboard->view_holder); furi_record_close(RECORD_GUI); diff --git a/applications/system/js_app/modules/js_submenu.c b/applications/system/js_app/modules/js_submenu.c index 058b32fd0..5ab9bef77 100644 --- a/applications/system/js_app/modules/js_submenu.c +++ b/applications/system/js_app/modules/js_submenu.c @@ -97,10 +97,9 @@ static void js_submenu_show(struct mjs* mjs) { view_holder_set_back_callback(submenu->view_holder, submenu_exit, submenu); view_holder_set_view(submenu->view_holder, submenu_get_view(submenu->submenu)); - view_holder_start(submenu->view_holder); api_lock_wait_unlock(submenu->lock); - view_holder_stop(submenu->view_holder); + view_holder_set_view(submenu->view_holder, NULL); view_holder_free(submenu->view_holder); furi_record_close(RECORD_GUI); api_lock_free(submenu->lock); diff --git a/applications/system/js_app/modules/js_textbox.c b/applications/system/js_app/modules/js_textbox.c index 33798b296..b90dbc153 100644 --- a/applications/system/js_app/modules/js_textbox.c +++ b/applications/system/js_app/modules/js_textbox.c @@ -125,7 +125,7 @@ static void js_textbox_is_open(struct mjs* mjs) { static void textbox_callback(void* context, uint32_t arg) { UNUSED(arg); JsTextboxInst* textbox = context; - view_holder_stop(textbox->view_holder); + view_holder_set_view(textbox->view_holder, NULL); textbox->is_shown = false; } @@ -145,7 +145,7 @@ static void js_textbox_show(struct mjs* mjs) { return; } - view_holder_start(textbox->view_holder); + view_holder_set_view(textbox->view_holder, text_box_get_view(textbox->text_box)); textbox->is_shown = true; mjs_return(mjs, MJS_UNDEFINED); @@ -155,7 +155,7 @@ static void js_textbox_close(struct mjs* mjs) { JsTextboxInst* textbox = get_this_ctx(mjs); if(!check_arg_count(mjs, 0)) return; - view_holder_stop(textbox->view_holder); + view_holder_set_view(textbox->view_holder, NULL); textbox->is_shown = false; mjs_return(mjs, MJS_UNDEFINED); @@ -180,7 +180,6 @@ static void* js_textbox_create(struct mjs* mjs, mjs_val_t* object) { textbox->view_holder = view_holder_alloc(); view_holder_attach_to_gui(textbox->view_holder, gui); view_holder_set_back_callback(textbox->view_holder, textbox_exit, textbox); - view_holder_set_view(textbox->view_holder, text_box_get_view(textbox->text_box)); *object = textbox_obj; return textbox; @@ -189,7 +188,7 @@ static void* js_textbox_create(struct mjs* mjs, mjs_val_t* object) { static void js_textbox_destroy(void* inst) { JsTextboxInst* textbox = inst; - view_holder_stop(textbox->view_holder); + view_holder_set_view(textbox->view_holder, NULL); view_holder_free(textbox->view_holder); textbox->view_holder = NULL; diff --git a/applications/system/js_app/modules/js_widget.c b/applications/system/js_app/modules/js_widget.c index 07be98033..16b058a17 100644 --- a/applications/system/js_app/modules/js_widget.c +++ b/applications/system/js_app/modules/js_widget.c @@ -825,7 +825,7 @@ static void js_widget_is_open(struct mjs* mjs) { static void widget_callback(void* context, uint32_t arg) { UNUSED(arg); JsWidgetInst* widget = context; - view_holder_stop(widget->view_holder); + view_holder_set_view(widget->view_holder, NULL); widget->is_shown = false; } @@ -845,7 +845,7 @@ static void js_widget_show(struct mjs* mjs) { return; } - view_holder_start(widget->view_holder); + view_holder_set_view(widget->view_holder, widget->view); widget->is_shown = true; mjs_return(mjs, MJS_UNDEFINED); @@ -855,7 +855,7 @@ static void js_widget_close(struct mjs* mjs) { JsWidgetInst* widget = get_this_ctx(mjs); if(!check_arg_count(mjs, 0)) return; - view_holder_stop(widget->view_holder); + view_holder_set_view(widget->view_holder, NULL); widget->is_shown = false; mjs_return(mjs, MJS_UNDEFINED); @@ -933,7 +933,6 @@ static void* js_widget_create(struct mjs* mjs, mjs_val_t* object) { widget->view_holder = view_holder_alloc(); view_holder_attach_to_gui(widget->view_holder, gui); view_holder_set_back_callback(widget->view_holder, widget_exit, widget); - view_holder_set_view(widget->view_holder, widget->view); *object = widget_obj; return widget; @@ -942,7 +941,7 @@ static void* js_widget_create(struct mjs* mjs, mjs_val_t* object) { static void js_widget_destroy(void* inst) { JsWidgetInst* widget = inst; - view_holder_stop(widget->view_holder); + view_holder_set_view(widget->view_holder, NULL); view_holder_free(widget->view_holder); widget->view_holder = NULL; diff --git a/applications/system/storage_move_to_sd/application.fam b/applications/system/storage_move_to_sd/application.fam deleted file mode 100644 index de47de055..000000000 --- a/applications/system/storage_move_to_sd/application.fam +++ /dev/null @@ -1,18 +0,0 @@ -App( - appid="storage_move_to_sd", - name="StorageMoveToSd", - apptype=FlipperAppType.SYSTEM, - entry_point="storage_move_to_sd_app", - requires=["gui", "storage"], - provides=["storage_move_to_sd_start"], - stack_size=2 * 1024, - order=30, -) - -App( - appid="storage_move_to_sd_start", - apptype=FlipperAppType.STARTUP, - entry_point="storage_move_to_sd_start", - requires=["storage"], - order=120, -) diff --git a/applications/system/storage_move_to_sd/scenes/storage_move_to_sd_scene.c b/applications/system/storage_move_to_sd/scenes/storage_move_to_sd_scene.c deleted file mode 100644 index 011bf47df..000000000 --- a/applications/system/storage_move_to_sd/scenes/storage_move_to_sd_scene.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "storage_move_to_sd_scene.h" - -// Generate scene on_enter handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, -void (*const storage_move_to_sd_on_enter_handlers[])(void*) = { -#include "storage_move_to_sd_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_event handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, -bool (*const storage_move_to_sd_on_event_handlers[])(void* context, SceneManagerEvent event) = { -#include "storage_move_to_sd_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_exit handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, -void (*const storage_move_to_sd_on_exit_handlers[])(void* context) = { -#include "storage_move_to_sd_scene_config.h" -}; -#undef ADD_SCENE - -// Initialize scene handlers configuration structure -const SceneManagerHandlers storage_move_to_sd_scene_handlers = { - .on_enter_handlers = storage_move_to_sd_on_enter_handlers, - .on_event_handlers = storage_move_to_sd_on_event_handlers, - .on_exit_handlers = storage_move_to_sd_on_exit_handlers, - .scene_num = StorageMoveToSdSceneNum, -}; diff --git a/applications/system/storage_move_to_sd/scenes/storage_move_to_sd_scene_config.h b/applications/system/storage_move_to_sd/scenes/storage_move_to_sd_scene_config.h deleted file mode 100644 index 1d7b2d25b..000000000 --- a/applications/system/storage_move_to_sd/scenes/storage_move_to_sd_scene_config.h +++ /dev/null @@ -1,2 +0,0 @@ -ADD_SCENE(storage_move_to_sd, confirm, Confirm) -ADD_SCENE(storage_move_to_sd, progress, Progress) diff --git a/applications/system/storage_move_to_sd/scenes/storage_move_to_sd_scene_confirm.c b/applications/system/storage_move_to_sd/scenes/storage_move_to_sd_scene_confirm.c deleted file mode 100644 index 08c9e2d7f..000000000 --- a/applications/system/storage_move_to_sd/scenes/storage_move_to_sd_scene_confirm.c +++ /dev/null @@ -1,70 +0,0 @@ -#include "../storage_move_to_sd.h" -#include -#include -#include - -static void storage_move_to_sd_scene_confirm_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - StorageMoveToSd* app = context; - furi_assert(app); - if(type == InputTypeShort) { - if(result == GuiButtonTypeRight) { - view_dispatcher_send_custom_event(app->view_dispatcher, MoveToSdCustomEventConfirm); - } else if(result == GuiButtonTypeLeft) { - view_dispatcher_send_custom_event(app->view_dispatcher, MoveToSdCustomEventExit); - } - } -} - -void storage_move_to_sd_scene_confirm_on_enter(void* context) { - StorageMoveToSd* app = context; - - widget_add_button_element( - app->widget, - GuiButtonTypeLeft, - "Cancel", - storage_move_to_sd_scene_confirm_widget_callback, - app); - widget_add_button_element( - app->widget, - GuiButtonTypeRight, - "Confirm", - storage_move_to_sd_scene_confirm_widget_callback, - app); - - widget_add_string_element( - app->widget, 64, 10, AlignCenter, AlignCenter, FontPrimary, "SD card inserted"); - widget_add_string_multiline_element( - app->widget, - 64, - 32, - AlignCenter, - AlignCenter, - FontSecondary, - "Move data from\ninternal storage to SD card?"); - - view_dispatcher_switch_to_view(app->view_dispatcher, StorageMoveToSdViewWidget); -} - -bool storage_move_to_sd_scene_confirm_on_event(void* context, SceneManagerEvent event) { - StorageMoveToSd* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == MoveToSdCustomEventConfirm) { - scene_manager_next_scene(app->scene_manager, StorageMoveToSdProgress); - consumed = true; - } else if(event.event == MoveToSdCustomEventExit) { - view_dispatcher_stop(app->view_dispatcher); - } - } - - return consumed; -} - -void storage_move_to_sd_scene_confirm_on_exit(void* context) { - StorageMoveToSd* app = context; - widget_reset(app->widget); -} diff --git a/applications/system/storage_move_to_sd/scenes/storage_move_to_sd_scene_progress.c b/applications/system/storage_move_to_sd/scenes/storage_move_to_sd_scene_progress.c deleted file mode 100644 index 7aa951bd8..000000000 --- a/applications/system/storage_move_to_sd/scenes/storage_move_to_sd_scene_progress.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "../storage_move_to_sd.h" - -void storage_move_to_sd_scene_progress_on_enter(void* context) { - StorageMoveToSd* app = context; - - widget_add_string_element( - app->widget, 64, 10, AlignCenter, AlignCenter, FontPrimary, "Moving..."); - - view_dispatcher_switch_to_view(app->view_dispatcher, StorageMoveToSdViewWidget); - - storage_move_to_sd_perform(); - view_dispatcher_send_custom_event(app->view_dispatcher, MoveToSdCustomEventExit); -} - -bool storage_move_to_sd_scene_progress_on_event(void* context, SceneManagerEvent event) { - StorageMoveToSd* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - view_dispatcher_stop(app->view_dispatcher); - } else if(event.type == SceneManagerEventTypeBack) { - consumed = true; - } - - return consumed; -} - -void storage_move_to_sd_scene_progress_on_exit(void* context) { - StorageMoveToSd* app = context; - widget_reset(app->widget); -} diff --git a/applications/system/storage_move_to_sd/storage_move_to_sd.c b/applications/system/storage_move_to_sd/storage_move_to_sd.c deleted file mode 100644 index 652c34c72..000000000 --- a/applications/system/storage_move_to_sd/storage_move_to_sd.c +++ /dev/null @@ -1,188 +0,0 @@ -#include "storage_move_to_sd.h" - -#include -#include -#include -#include -#include - -#define TAG "MoveToSd" - -#define MOVE_SRC STORAGE_INT_PATH_PREFIX -#define MOVE_DST STORAGE_EXT_PATH_PREFIX - -static bool storage_move_to_sd_check_entry(const char* name, FileInfo* fileinfo, void* ctx) { - UNUSED(ctx); - if(file_info_is_dir(fileinfo)) { - return true; - } - - return name && (*name != '.'); -} - -bool storage_move_to_sd_perform(void) { - Storage* storage = furi_record_open(RECORD_STORAGE); - - DirWalk* dir_walk = dir_walk_alloc(storage); - dir_walk_set_recursive(dir_walk, false); - dir_walk_set_filter_cb(dir_walk, storage_move_to_sd_check_entry, NULL); - - FuriString *path_src, *path_dst; - - path_dst = furi_string_alloc(); - path_src = furi_string_alloc(); - - if(dir_walk_open(dir_walk, STORAGE_INT_PATH_PREFIX)) { - while(dir_walk_read(dir_walk, path_src, NULL) == DirWalkOK) { - furi_string_set(path_dst, path_src); - furi_string_replace_at( - path_dst, 0, strlen(STORAGE_INT_PATH_PREFIX), STORAGE_EXT_PATH_PREFIX); - - storage_common_merge( - storage, furi_string_get_cstr(path_src), furi_string_get_cstr(path_dst)); - storage_simply_remove_recursive(storage, furi_string_get_cstr(path_src)); - } - } - - dir_walk_free(dir_walk); - furi_string_free(path_dst); - furi_string_free(path_src); - - furi_record_close(RECORD_STORAGE); - - return false; -} - -static bool storage_move_to_sd_check(void) { - Storage* storage = furi_record_open(RECORD_STORAGE); - - bool should_migrate = false; - - DirWalk* dir_walk = dir_walk_alloc(storage); - dir_walk_set_recursive(dir_walk, false); - dir_walk_set_filter_cb(dir_walk, storage_move_to_sd_check_entry, NULL); - - FuriString* name; - name = furi_string_alloc(); - - if(dir_walk_open(dir_walk, STORAGE_INT_PATH_PREFIX)) { - // if at least 1 entry is present, we should migrate - should_migrate = (dir_walk_read(dir_walk, name, NULL) == DirWalkOK); - } - - dir_walk_free(dir_walk); - furi_string_free(name); - - furi_record_close(RECORD_STORAGE); - - return should_migrate; -} - -static bool storage_move_to_sd_custom_event_callback(void* context, uint32_t event) { - furi_assert(context); - StorageMoveToSd* app = context; - return scene_manager_handle_custom_event(app->scene_manager, event); -} - -static bool storage_move_to_sd_back_event_callback(void* context) { - furi_assert(context); - StorageMoveToSd* app = context; - return scene_manager_handle_back_event(app->scene_manager); -} - -static void storage_move_to_sd_unmount_callback(const void* message, void* context) { - StorageMoveToSd* app = context; - furi_assert(app); - const StorageEvent* storage_event = message; - - if((storage_event->type == StorageEventTypeCardUnmount) || - (storage_event->type == StorageEventTypeCardMountError)) { - view_dispatcher_send_custom_event(app->view_dispatcher, MoveToSdCustomEventExit); - } -} - -static StorageMoveToSd* storage_move_to_sd_alloc(void) { - StorageMoveToSd* app = malloc(sizeof(StorageMoveToSd)); - - app->gui = furi_record_open(RECORD_GUI); - app->notifications = furi_record_open(RECORD_NOTIFICATION); - - app->view_dispatcher = view_dispatcher_alloc(); - app->scene_manager = scene_manager_alloc(&storage_move_to_sd_scene_handlers, app); - - view_dispatcher_enable_queue(app->view_dispatcher); - view_dispatcher_set_event_callback_context(app->view_dispatcher, app); - - view_dispatcher_set_custom_event_callback( - app->view_dispatcher, storage_move_to_sd_custom_event_callback); - view_dispatcher_set_navigation_event_callback( - app->view_dispatcher, storage_move_to_sd_back_event_callback); - - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - - app->widget = widget_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, StorageMoveToSdViewWidget, widget_get_view(app->widget)); - - scene_manager_next_scene(app->scene_manager, StorageMoveToSdConfirm); - - Storage* storage = furi_record_open(RECORD_STORAGE); - app->sub = furi_pubsub_subscribe( - storage_get_pubsub(storage), storage_move_to_sd_unmount_callback, app); - furi_record_close(RECORD_STORAGE); - - return app; -} - -static void storage_move_to_sd_free(StorageMoveToSd* app) { - Storage* storage = furi_record_open(RECORD_STORAGE); - furi_pubsub_unsubscribe(storage_get_pubsub(storage), app->sub); - furi_record_close(RECORD_STORAGE); - furi_record_close(RECORD_NOTIFICATION); - - view_dispatcher_remove_view(app->view_dispatcher, StorageMoveToSdViewWidget); - widget_free(app->widget); - view_dispatcher_free(app->view_dispatcher); - scene_manager_free(app->scene_manager); - - furi_record_close(RECORD_GUI); - - free(app); -} - -int32_t storage_move_to_sd_app(void* p) { - UNUSED(p); - - if(storage_move_to_sd_check()) { - StorageMoveToSd* app = storage_move_to_sd_alloc(); - notification_message(app->notifications, &sequence_display_backlight_on); - view_dispatcher_run(app->view_dispatcher); - storage_move_to_sd_free(app); - } else { - FURI_LOG_I(TAG, "Nothing to move"); - } - - return 0; -} - -static void storage_move_to_sd_mount_callback(const void* message, void* context) { - UNUSED(context); - - const StorageEvent* storage_event = message; - - if(storage_event->type == StorageEventTypeCardMount) { - Loader* loader = furi_record_open(RECORD_LOADER); - loader_start(loader, "StorageMoveToSd", NULL, NULL); - furi_record_close(RECORD_LOADER); - } -} - -int32_t storage_move_to_sd_start(void* p) { - UNUSED(p); - Storage* storage = furi_record_open(RECORD_STORAGE); - - furi_pubsub_subscribe(storage_get_pubsub(storage), storage_move_to_sd_mount_callback, NULL); - - furi_record_close(RECORD_STORAGE); - return 0; -} diff --git a/applications/system/storage_move_to_sd/storage_move_to_sd.h b/applications/system/storage_move_to_sd/storage_move_to_sd.h deleted file mode 100644 index 135f3e9b0..000000000 --- a/applications/system/storage_move_to_sd/storage_move_to_sd.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "scenes/storage_move_to_sd_scene.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - MoveToSdCustomEventExit, - MoveToSdCustomEventConfirm, -} MoveToSdCustomEvent; - -typedef struct { - // records - Gui* gui; - Widget* widget; - NotificationApp* notifications; - - // view management - SceneManager* scene_manager; - ViewDispatcher* view_dispatcher; - - FuriPubSubSubscription* sub; - -} StorageMoveToSd; - -typedef enum { - StorageMoveToSdViewWidget, -} StorageMoveToSdView; - -bool storage_move_to_sd_perform(void); - -#ifdef __cplusplus -} -#endif diff --git a/applications/system/updater/updater.c b/applications/system/updater/updater.c index 4c7fd29e9..15d7dd3a9 100644 --- a/applications/system/updater/updater.c +++ b/applications/system/updater/updater.c @@ -47,8 +47,6 @@ Updater* updater_alloc(const char* arg) { updater->view_dispatcher = view_dispatcher_alloc(); updater->scene_manager = scene_manager_alloc(&updater_scene_handlers, updater); - view_dispatcher_enable_queue(updater->view_dispatcher); - view_dispatcher_set_event_callback_context(updater->view_dispatcher, updater); view_dispatcher_set_custom_event_callback( updater->view_dispatcher, updater_custom_event_callback); diff --git a/applications/system/updater/util/update_task.c b/applications/system/updater/util/update_task.c index c9449b418..eaddbeeab 100644 --- a/applications/system/updater/util/update_task.c +++ b/applications/system/updater/util/update_task.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #define TAG "UpdWorker" diff --git a/applications/system/updater/util/update_task_worker_backup.c b/applications/system/updater/util/update_task_worker_backup.c index 5a69f4654..bcf1fd141 100644 --- a/applications/system/updater/util/update_task_worker_backup.c +++ b/applications/system/updater/util/update_task_worker_backup.c @@ -13,7 +13,7 @@ #include #include -#define FIRSTBOOT_FLAG_PATH CFG_PATH("momentum_firstboot.flag") +#define FIRSTBOOT_FLAG_PATH INT_PATH(".momentum_firstboot.flag") #define TAG "UpdWorkerBackup" @@ -173,7 +173,11 @@ static bool update_task_post_update(UpdateTask* update_task) { tmp_path = furi_string_alloc_set(update_task->update_path); storage_common_rename( update_task->storage, - CFG_PATH("firstboot.flag"), // Poor naming, shouldn't be generic for all FW + EXT_PATH(".config/firstboot.flag"), // Poor naming, shouldn't be generic for all FW + FIRSTBOOT_FLAG_PATH); + storage_common_rename( + update_task->storage, + EXT_PATH(".config/momentum_firstboot.flag"), // Migrate to int on ext FIRSTBOOT_FLAG_PATH); if(storage_common_stat(update_task->storage, FIRSTBOOT_FLAG_PATH, NULL) == FSE_NOT_EXIST) { diff --git a/applications/system/updater/util/update_task_worker_flasher.c b/applications/system/updater/util/update_task_worker_flasher.c index e5fd04559..6ff00959d 100644 --- a/applications/system/updater/util/update_task_worker_flasher.c +++ b/applications/system/updater/util/update_task_worker_flasher.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include diff --git a/assets/dolphin/blocking/L0_NewMail_128x51/frame_0.png b/assets/dolphin/blocking/L0_NewMail_128x51/frame_0.png index 5f7f5fa42..d948c55bd 100644 Binary files a/assets/dolphin/blocking/L0_NewMail_128x51/frame_0.png and b/assets/dolphin/blocking/L0_NewMail_128x51/frame_0.png differ diff --git a/assets/dolphin/blocking/L0_NewMail_128x51/frame_1.png b/assets/dolphin/blocking/L0_NewMail_128x51/frame_1.png index db9bf227b..13be20165 100644 Binary files a/assets/dolphin/blocking/L0_NewMail_128x51/frame_1.png and b/assets/dolphin/blocking/L0_NewMail_128x51/frame_1.png differ diff --git a/assets/dolphin/blocking/L0_NewMail_128x51/frame_2.png b/assets/dolphin/blocking/L0_NewMail_128x51/frame_2.png index 5394851f5..432db2ed8 100644 Binary files a/assets/dolphin/blocking/L0_NewMail_128x51/frame_2.png and b/assets/dolphin/blocking/L0_NewMail_128x51/frame_2.png differ diff --git a/assets/dolphin/blocking/L0_NewMail_128x51/frame_3.png b/assets/dolphin/blocking/L0_NewMail_128x51/frame_3.png index d16966fb4..8a9de358b 100644 Binary files a/assets/dolphin/blocking/L0_NewMail_128x51/frame_3.png and b/assets/dolphin/blocking/L0_NewMail_128x51/frame_3.png differ diff --git a/assets/dolphin/blocking/L0_NoDb_128x51/frame_0.png b/assets/dolphin/blocking/L0_NoDb_128x51/frame_0.png index 1a62c29da..acb9a1a35 100644 Binary files a/assets/dolphin/blocking/L0_NoDb_128x51/frame_0.png and b/assets/dolphin/blocking/L0_NoDb_128x51/frame_0.png differ diff --git a/assets/dolphin/blocking/L0_SdBad_128x51/frame_0.png b/assets/dolphin/blocking/L0_SdBad_128x51/frame_0.png index cab8e0573..48f140046 100644 Binary files a/assets/dolphin/blocking/L0_SdBad_128x51/frame_0.png and b/assets/dolphin/blocking/L0_SdBad_128x51/frame_0.png differ diff --git a/assets/dolphin/blocking/L0_SdOk_128x51/frame_0.png b/assets/dolphin/blocking/L0_SdOk_128x51/frame_0.png index fa7e4140b..ee4ec1ba8 100644 Binary files a/assets/dolphin/blocking/L0_SdOk_128x51/frame_0.png and b/assets/dolphin/blocking/L0_SdOk_128x51/frame_0.png differ diff --git a/assets/dolphin/blocking/L0_Url_128x51/frame_0.png b/assets/dolphin/blocking/L0_Url_128x51/frame_0.png index 347541d4c..aad40a5ae 100644 Binary files a/assets/dolphin/blocking/L0_Url_128x51/frame_0.png and b/assets/dolphin/blocking/L0_Url_128x51/frame_0.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_0.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_0.png index 753497fae..73ed8998c 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_0.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_1.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_1.png index aedd7e85a..7955637f6 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_1.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_10.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_10.png index d573c781b..d888edd76 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_10.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_10.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_11.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_11.png index 86c1fb73b..e3da336a7 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_11.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_11.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_12.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_12.png index 061f9a26f..78068bfaa 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_12.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_12.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_13.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_13.png index bcb0bc77a..ad07012e1 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_13.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_13.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_14.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_14.png index 9f9a69250..a7e51895b 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_14.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_14.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_15.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_15.png index 351f2c9b8..f2b8e9bb9 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_15.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_15.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_16.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_16.png index e77cb28ec..46c41c92d 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_16.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_16.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_17.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_17.png index 8c1e85a02..569dcb1b8 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_17.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_17.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_18.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_18.png index cbaadf12b..819f57802 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_18.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_18.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_19.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_19.png index 0e926df25..29885e341 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_19.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_19.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_2.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_2.png index 67b294b31..20ef24310 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_2.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_20.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_20.png index 7a80cf565..71dbc84b2 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_20.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_20.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_21.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_21.png index 69ad187bb..fdd38b5c2 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_21.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_21.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_22.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_22.png index c83f6d741..2e66dd0fb 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_22.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_22.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_23.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_23.png index f3a007fb3..87ebe6935 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_23.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_23.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_24.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_24.png index dd8421f86..1258e162d 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_24.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_24.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_25.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_25.png index 266d3cd7d..0e9ffcbb9 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_25.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_25.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_26.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_26.png index 66e307898..2b89d892b 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_26.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_26.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_27.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_27.png index ab033810a..f4cbd8bda 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_27.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_27.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_28.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_28.png index 897dcb051..eb4155d70 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_28.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_28.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_29.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_29.png index 0aa3c865a..25811796a 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_29.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_29.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_3.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_3.png index 7d3365ee4..b71bcffb9 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_3.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_30.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_30.png index 1142b205b..0f32291ec 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_30.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_30.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_31.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_31.png index f1c13be32..a02d6363b 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_31.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_31.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_32.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_32.png index 67ab4b589..d3de10b98 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_32.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_32.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_33.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_33.png index 80f761c2b..4e77f139b 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_33.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_33.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_34.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_34.png index 56f509c5b..3d5f14207 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_34.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_34.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_35.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_35.png index 50cc95411..b04190d48 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_35.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_35.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_36.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_36.png index e6b656923..f19e1e4fc 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_36.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_36.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_37.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_37.png index dfde848c2..8380dec91 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_37.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_37.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_38.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_38.png index 873f7650d..c08c783a7 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_38.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_38.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_39.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_39.png index 9c6f7110c..27f87e640 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_39.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_39.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_4.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_4.png index b5dd2c1b9..d2b21d7f0 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_4.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_40.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_40.png index c6603542e..b19ec36eb 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_40.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_40.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_41.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_41.png index b12c4068d..1632162fc 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_41.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_41.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_42.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_42.png index 3e3415af6..6bae8af86 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_42.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_42.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_43.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_43.png index d918354a4..e4dc1625a 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_43.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_43.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_44.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_44.png index 4b3e29fe1..5854b6d2f 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_44.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_44.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_45.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_45.png index 78d6ab85e..233641453 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_45.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_45.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_5.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_5.png index 544848d81..2f1342a4a 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_5.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_6.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_6.png index 9648bad93..29b6ef25b 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_6.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_7.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_7.png index d6078bdf1..4dfb4cac3 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_7.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_8.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_8.png index 0e018b6df..55e3ebcff 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_8.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_8.png differ diff --git a/assets/dolphin/external/L1_3d_printing_128x64/frame_9.png b/assets/dolphin/external/L1_3d_printing_128x64/frame_9.png index 8fb2567b0..86c129082 100644 Binary files a/assets/dolphin/external/L1_3d_printing_128x64/frame_9.png and b/assets/dolphin/external/L1_3d_printing_128x64/frame_9.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_0.png b/assets/dolphin/external/L1_Akira_128x64/frame_0.png index 36c1bbd49..bef9d522d 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_0.png and b/assets/dolphin/external/L1_Akira_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_1.png b/assets/dolphin/external/L1_Akira_128x64/frame_1.png index 1950347a6..4d476beed 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_1.png and b/assets/dolphin/external/L1_Akira_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_10.png b/assets/dolphin/external/L1_Akira_128x64/frame_10.png index 65a0154d4..ca01a68d1 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_10.png and b/assets/dolphin/external/L1_Akira_128x64/frame_10.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_11.png b/assets/dolphin/external/L1_Akira_128x64/frame_11.png index f7c086431..f767fe332 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_11.png and b/assets/dolphin/external/L1_Akira_128x64/frame_11.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_12.png b/assets/dolphin/external/L1_Akira_128x64/frame_12.png index e3bfd179d..4d800a109 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_12.png and b/assets/dolphin/external/L1_Akira_128x64/frame_12.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_13.png b/assets/dolphin/external/L1_Akira_128x64/frame_13.png index 0094ab5ae..01d8b8c9a 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_13.png and b/assets/dolphin/external/L1_Akira_128x64/frame_13.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_14.png b/assets/dolphin/external/L1_Akira_128x64/frame_14.png index b36fd051f..18da66c10 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_14.png and b/assets/dolphin/external/L1_Akira_128x64/frame_14.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_15.png b/assets/dolphin/external/L1_Akira_128x64/frame_15.png index 33607328a..529ae406e 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_15.png and b/assets/dolphin/external/L1_Akira_128x64/frame_15.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_16.png b/assets/dolphin/external/L1_Akira_128x64/frame_16.png index e115834ef..8f66d531c 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_16.png and b/assets/dolphin/external/L1_Akira_128x64/frame_16.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_17.png b/assets/dolphin/external/L1_Akira_128x64/frame_17.png index 8e5fa20d8..cf37db346 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_17.png and b/assets/dolphin/external/L1_Akira_128x64/frame_17.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_18.png b/assets/dolphin/external/L1_Akira_128x64/frame_18.png index 6a658e0e2..87069ea8e 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_18.png and b/assets/dolphin/external/L1_Akira_128x64/frame_18.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_19.png b/assets/dolphin/external/L1_Akira_128x64/frame_19.png index cba72f16f..48e607096 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_19.png and b/assets/dolphin/external/L1_Akira_128x64/frame_19.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_2.png b/assets/dolphin/external/L1_Akira_128x64/frame_2.png index 9f4cc1fb9..72febfa30 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_2.png and b/assets/dolphin/external/L1_Akira_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_20.png b/assets/dolphin/external/L1_Akira_128x64/frame_20.png index 457fa7a00..6bcc87a38 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_20.png and b/assets/dolphin/external/L1_Akira_128x64/frame_20.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_21.png b/assets/dolphin/external/L1_Akira_128x64/frame_21.png index 727511100..ca775046a 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_21.png and b/assets/dolphin/external/L1_Akira_128x64/frame_21.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_22.png b/assets/dolphin/external/L1_Akira_128x64/frame_22.png index 213e05771..c90432ebe 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_22.png and b/assets/dolphin/external/L1_Akira_128x64/frame_22.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_23.png b/assets/dolphin/external/L1_Akira_128x64/frame_23.png index 5d3571db8..b49348856 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_23.png and b/assets/dolphin/external/L1_Akira_128x64/frame_23.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_24.png b/assets/dolphin/external/L1_Akira_128x64/frame_24.png index e54d47e29..b5ea1a21c 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_24.png and b/assets/dolphin/external/L1_Akira_128x64/frame_24.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_25.png b/assets/dolphin/external/L1_Akira_128x64/frame_25.png index 26c944d16..9da0a4cc6 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_25.png and b/assets/dolphin/external/L1_Akira_128x64/frame_25.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_26.png b/assets/dolphin/external/L1_Akira_128x64/frame_26.png index 2972318cd..1805bdb95 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_26.png and b/assets/dolphin/external/L1_Akira_128x64/frame_26.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_27.png b/assets/dolphin/external/L1_Akira_128x64/frame_27.png index 397face78..37a820798 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_27.png and b/assets/dolphin/external/L1_Akira_128x64/frame_27.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_28.png b/assets/dolphin/external/L1_Akira_128x64/frame_28.png index 6ca246f57..3b12a422d 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_28.png and b/assets/dolphin/external/L1_Akira_128x64/frame_28.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_29.png b/assets/dolphin/external/L1_Akira_128x64/frame_29.png index 8bcc83a1d..b4a35158e 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_29.png and b/assets/dolphin/external/L1_Akira_128x64/frame_29.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_3.png b/assets/dolphin/external/L1_Akira_128x64/frame_3.png index 7a1d2b36e..9afce23c9 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_3.png and b/assets/dolphin/external/L1_Akira_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_30.png b/assets/dolphin/external/L1_Akira_128x64/frame_30.png index 9f477f8d7..870255497 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_30.png and b/assets/dolphin/external/L1_Akira_128x64/frame_30.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_31.png b/assets/dolphin/external/L1_Akira_128x64/frame_31.png index 4f2deb5c5..68249a4d5 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_31.png and b/assets/dolphin/external/L1_Akira_128x64/frame_31.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_32.png b/assets/dolphin/external/L1_Akira_128x64/frame_32.png index 4f59f9955..5eb2b770b 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_32.png and b/assets/dolphin/external/L1_Akira_128x64/frame_32.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_33.png b/assets/dolphin/external/L1_Akira_128x64/frame_33.png index 1adf3d351..795b88fb4 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_33.png and b/assets/dolphin/external/L1_Akira_128x64/frame_33.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_34.png b/assets/dolphin/external/L1_Akira_128x64/frame_34.png index 5ffc55f75..e5a97b138 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_34.png and b/assets/dolphin/external/L1_Akira_128x64/frame_34.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_35.png b/assets/dolphin/external/L1_Akira_128x64/frame_35.png index 9a101f0aa..7a2154c4b 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_35.png and b/assets/dolphin/external/L1_Akira_128x64/frame_35.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_4.png b/assets/dolphin/external/L1_Akira_128x64/frame_4.png index ea42d75d6..55f3b66a6 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_4.png and b/assets/dolphin/external/L1_Akira_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_5.png b/assets/dolphin/external/L1_Akira_128x64/frame_5.png index c347d3035..6b5666677 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_5.png and b/assets/dolphin/external/L1_Akira_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_6.png b/assets/dolphin/external/L1_Akira_128x64/frame_6.png index 07a7c70c0..f16295ffd 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_6.png and b/assets/dolphin/external/L1_Akira_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_7.png b/assets/dolphin/external/L1_Akira_128x64/frame_7.png index 275f2a357..51f1f5c40 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_7.png and b/assets/dolphin/external/L1_Akira_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_8.png b/assets/dolphin/external/L1_Akira_128x64/frame_8.png index 1feb3e875..e44453afa 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_8.png and b/assets/dolphin/external/L1_Akira_128x64/frame_8.png differ diff --git a/assets/dolphin/external/L1_Akira_128x64/frame_9.png b/assets/dolphin/external/L1_Akira_128x64/frame_9.png index e0ba8250f..aed5833f3 100644 Binary files a/assets/dolphin/external/L1_Akira_128x64/frame_9.png and b/assets/dolphin/external/L1_Akira_128x64/frame_9.png differ diff --git a/assets/dolphin/external/L1_Boxing_128x64/frame_0.png b/assets/dolphin/external/L1_Boxing_128x64/frame_0.png index b6b2c75b8..9dcab2323 100644 Binary files a/assets/dolphin/external/L1_Boxing_128x64/frame_0.png and b/assets/dolphin/external/L1_Boxing_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L1_Boxing_128x64/frame_1.png b/assets/dolphin/external/L1_Boxing_128x64/frame_1.png index 347d71cc2..ecbd27419 100644 Binary files a/assets/dolphin/external/L1_Boxing_128x64/frame_1.png and b/assets/dolphin/external/L1_Boxing_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L1_Boxing_128x64/frame_2.png b/assets/dolphin/external/L1_Boxing_128x64/frame_2.png index 51a7fd236..1243ee277 100644 Binary files a/assets/dolphin/external/L1_Boxing_128x64/frame_2.png and b/assets/dolphin/external/L1_Boxing_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L1_Boxing_128x64/frame_3.png b/assets/dolphin/external/L1_Boxing_128x64/frame_3.png index 7004e10c3..0972a2817 100644 Binary files a/assets/dolphin/external/L1_Boxing_128x64/frame_3.png and b/assets/dolphin/external/L1_Boxing_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L1_Boxing_128x64/frame_4.png b/assets/dolphin/external/L1_Boxing_128x64/frame_4.png index 556cb8948..eef11402b 100644 Binary files a/assets/dolphin/external/L1_Boxing_128x64/frame_4.png and b/assets/dolphin/external/L1_Boxing_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L1_Boxing_128x64/frame_5.png b/assets/dolphin/external/L1_Boxing_128x64/frame_5.png index fd6170340..cf2299b28 100644 Binary files a/assets/dolphin/external/L1_Boxing_128x64/frame_5.png and b/assets/dolphin/external/L1_Boxing_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L1_Boxing_128x64/frame_6.png b/assets/dolphin/external/L1_Boxing_128x64/frame_6.png index 34839517c..853d85fb7 100644 Binary files a/assets/dolphin/external/L1_Boxing_128x64/frame_6.png and b/assets/dolphin/external/L1_Boxing_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L1_Cry_128x64/frame_0.png b/assets/dolphin/external/L1_Cry_128x64/frame_0.png index b2636f005..feeb30cb6 100644 Binary files a/assets/dolphin/external/L1_Cry_128x64/frame_0.png and b/assets/dolphin/external/L1_Cry_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L1_Cry_128x64/frame_1.png b/assets/dolphin/external/L1_Cry_128x64/frame_1.png index e73499e94..df0abf137 100644 Binary files a/assets/dolphin/external/L1_Cry_128x64/frame_1.png and b/assets/dolphin/external/L1_Cry_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L1_Cry_128x64/frame_2.png b/assets/dolphin/external/L1_Cry_128x64/frame_2.png index 16005a990..3f3ef6666 100644 Binary files a/assets/dolphin/external/L1_Cry_128x64/frame_2.png and b/assets/dolphin/external/L1_Cry_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L1_Cry_128x64/frame_3.png b/assets/dolphin/external/L1_Cry_128x64/frame_3.png index 02e833dec..e0c975bea 100644 Binary files a/assets/dolphin/external/L1_Cry_128x64/frame_3.png and b/assets/dolphin/external/L1_Cry_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L1_Cry_128x64/frame_4.png b/assets/dolphin/external/L1_Cry_128x64/frame_4.png index 3f7dff4db..4e2e80240 100644 Binary files a/assets/dolphin/external/L1_Cry_128x64/frame_4.png and b/assets/dolphin/external/L1_Cry_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L1_Cry_128x64/frame_5.png b/assets/dolphin/external/L1_Cry_128x64/frame_5.png index 385106787..0a3285397 100644 Binary files a/assets/dolphin/external/L1_Cry_128x64/frame_5.png and b/assets/dolphin/external/L1_Cry_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L1_Cry_128x64/frame_6.png b/assets/dolphin/external/L1_Cry_128x64/frame_6.png index 7871674db..635c1771e 100644 Binary files a/assets/dolphin/external/L1_Cry_128x64/frame_6.png and b/assets/dolphin/external/L1_Cry_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L1_Cry_128x64/frame_7.png b/assets/dolphin/external/L1_Cry_128x64/frame_7.png index 5865e91e1..f1f78883f 100644 Binary files a/assets/dolphin/external/L1_Cry_128x64/frame_7.png and b/assets/dolphin/external/L1_Cry_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L1_Furippa1_128x64/frame_0.png b/assets/dolphin/external/L1_Furippa1_128x64/frame_0.png index 396ec251a..8be19d3c8 100644 Binary files a/assets/dolphin/external/L1_Furippa1_128x64/frame_0.png and b/assets/dolphin/external/L1_Furippa1_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L1_Furippa1_128x64/frame_1.png b/assets/dolphin/external/L1_Furippa1_128x64/frame_1.png index 2a497f85a..86b68b5dc 100644 Binary files a/assets/dolphin/external/L1_Furippa1_128x64/frame_1.png and b/assets/dolphin/external/L1_Furippa1_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L1_Furippa1_128x64/frame_10.png b/assets/dolphin/external/L1_Furippa1_128x64/frame_10.png index d33f1e416..755fb3e86 100644 Binary files a/assets/dolphin/external/L1_Furippa1_128x64/frame_10.png and b/assets/dolphin/external/L1_Furippa1_128x64/frame_10.png differ diff --git a/assets/dolphin/external/L1_Furippa1_128x64/frame_11.png b/assets/dolphin/external/L1_Furippa1_128x64/frame_11.png index e5ee82f70..e513b85ca 100644 Binary files a/assets/dolphin/external/L1_Furippa1_128x64/frame_11.png and b/assets/dolphin/external/L1_Furippa1_128x64/frame_11.png differ diff --git a/assets/dolphin/external/L1_Furippa1_128x64/frame_12.png b/assets/dolphin/external/L1_Furippa1_128x64/frame_12.png index f3059dde7..867f8d09f 100644 Binary files a/assets/dolphin/external/L1_Furippa1_128x64/frame_12.png and b/assets/dolphin/external/L1_Furippa1_128x64/frame_12.png differ diff --git a/assets/dolphin/external/L1_Furippa1_128x64/frame_13.png b/assets/dolphin/external/L1_Furippa1_128x64/frame_13.png index 5d1ff45be..45fd1ec4e 100644 Binary files a/assets/dolphin/external/L1_Furippa1_128x64/frame_13.png and b/assets/dolphin/external/L1_Furippa1_128x64/frame_13.png differ diff --git a/assets/dolphin/external/L1_Furippa1_128x64/frame_14.png b/assets/dolphin/external/L1_Furippa1_128x64/frame_14.png index d46f62e89..1390e1297 100644 Binary files a/assets/dolphin/external/L1_Furippa1_128x64/frame_14.png and b/assets/dolphin/external/L1_Furippa1_128x64/frame_14.png differ diff --git a/assets/dolphin/external/L1_Furippa1_128x64/frame_15.png b/assets/dolphin/external/L1_Furippa1_128x64/frame_15.png index ec11dbd03..d9ef6edbb 100644 Binary files a/assets/dolphin/external/L1_Furippa1_128x64/frame_15.png and b/assets/dolphin/external/L1_Furippa1_128x64/frame_15.png differ diff --git a/assets/dolphin/external/L1_Furippa1_128x64/frame_16.png b/assets/dolphin/external/L1_Furippa1_128x64/frame_16.png index 720e95f9e..0dec63de6 100644 Binary files a/assets/dolphin/external/L1_Furippa1_128x64/frame_16.png and b/assets/dolphin/external/L1_Furippa1_128x64/frame_16.png differ diff --git a/assets/dolphin/external/L1_Furippa1_128x64/frame_17.png b/assets/dolphin/external/L1_Furippa1_128x64/frame_17.png index 7debe764f..4fc9ea1d2 100644 Binary files a/assets/dolphin/external/L1_Furippa1_128x64/frame_17.png and b/assets/dolphin/external/L1_Furippa1_128x64/frame_17.png differ diff --git a/assets/dolphin/external/L1_Furippa1_128x64/frame_18.png b/assets/dolphin/external/L1_Furippa1_128x64/frame_18.png index d3674a02b..7ab4cf607 100644 Binary files a/assets/dolphin/external/L1_Furippa1_128x64/frame_18.png and b/assets/dolphin/external/L1_Furippa1_128x64/frame_18.png differ diff --git a/assets/dolphin/external/L1_Furippa1_128x64/frame_2.png b/assets/dolphin/external/L1_Furippa1_128x64/frame_2.png index ba4435157..9fa964345 100644 Binary files a/assets/dolphin/external/L1_Furippa1_128x64/frame_2.png and b/assets/dolphin/external/L1_Furippa1_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L1_Furippa1_128x64/frame_3.png b/assets/dolphin/external/L1_Furippa1_128x64/frame_3.png index c0ee41623..bba35b23b 100644 Binary files a/assets/dolphin/external/L1_Furippa1_128x64/frame_3.png and b/assets/dolphin/external/L1_Furippa1_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L1_Furippa1_128x64/frame_4.png b/assets/dolphin/external/L1_Furippa1_128x64/frame_4.png index ecda81274..aa0c34ec9 100644 Binary files a/assets/dolphin/external/L1_Furippa1_128x64/frame_4.png and b/assets/dolphin/external/L1_Furippa1_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L1_Furippa1_128x64/frame_5.png b/assets/dolphin/external/L1_Furippa1_128x64/frame_5.png index e8662b2eb..9a706e61e 100644 Binary files a/assets/dolphin/external/L1_Furippa1_128x64/frame_5.png and b/assets/dolphin/external/L1_Furippa1_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L1_Furippa1_128x64/frame_6.png b/assets/dolphin/external/L1_Furippa1_128x64/frame_6.png index 29cadd14e..c1373b058 100644 Binary files a/assets/dolphin/external/L1_Furippa1_128x64/frame_6.png and b/assets/dolphin/external/L1_Furippa1_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L1_Furippa1_128x64/frame_7.png b/assets/dolphin/external/L1_Furippa1_128x64/frame_7.png index 18e793b58..8be19d3c8 100644 Binary files a/assets/dolphin/external/L1_Furippa1_128x64/frame_7.png and b/assets/dolphin/external/L1_Furippa1_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L1_Furippa1_128x64/frame_8.png b/assets/dolphin/external/L1_Furippa1_128x64/frame_8.png index 34b2e4001..24b61edb6 100644 Binary files a/assets/dolphin/external/L1_Furippa1_128x64/frame_8.png and b/assets/dolphin/external/L1_Furippa1_128x64/frame_8.png differ diff --git a/assets/dolphin/external/L1_Furippa1_128x64/frame_9.png b/assets/dolphin/external/L1_Furippa1_128x64/frame_9.png index d192f2e34..f7976f232 100644 Binary files a/assets/dolphin/external/L1_Furippa1_128x64/frame_9.png and b/assets/dolphin/external/L1_Furippa1_128x64/frame_9.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_0.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_0.png index 8b8dc80bc..b316a8e32 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_0.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_1.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_1.png index 956de6170..eb259d993 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_1.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_10.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_10.png index 93fdaa076..1339ea3ac 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_10.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_10.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_11.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_11.png index a4e194825..4acf44972 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_11.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_11.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_12.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_12.png index 9cbcbd070..fb9042e69 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_12.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_12.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_13.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_13.png index a745cdb03..1ddea3436 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_13.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_13.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_14.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_14.png index 768f471ec..91b4660e6 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_14.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_14.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_15.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_15.png index 2f50fb8c9..5f1e17f24 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_15.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_15.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_16.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_16.png index fc7b76696..15d6f55a7 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_16.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_16.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_17.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_17.png index 013e2008a..324e6440c 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_17.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_17.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_18.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_18.png index 795120e77..4ad5a7f91 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_18.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_18.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_19.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_19.png index 52061a5a2..372e7f360 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_19.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_19.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_2.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_2.png index 10afed391..d6b0fb95e 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_2.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_20.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_20.png index 52f87f3a8..287800454 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_20.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_20.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_21.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_21.png index 9696e0b5c..cb7b04b84 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_21.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_21.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_22.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_22.png index d23ee492b..ebab212e2 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_22.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_22.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_23.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_23.png index 9d368900c..55d2e5695 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_23.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_23.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_24.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_24.png index daf0788ad..df78c0887 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_24.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_24.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_25.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_25.png index b40333654..9d71ca41b 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_25.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_25.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_26.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_26.png index 9d499f23d..ea66720dd 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_26.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_26.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_27.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_27.png index 0291dfb58..0ee0b2135 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_27.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_27.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_28.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_28.png index 54a889d81..02b31050b 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_28.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_28.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_29.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_29.png index ba79b3b88..c00255748 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_29.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_29.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_3.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_3.png index bedf366c6..ddbbeae86 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_3.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_30.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_30.png index 0731760df..8d9176c4c 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_30.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_30.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_31.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_31.png index 898efdc4b..d73a65583 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_31.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_31.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_32.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_32.png index 39f5db8a0..c97abe79b 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_32.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_32.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_33.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_33.png index bee4cff08..20299c04d 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_33.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_33.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_34.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_34.png index 969b91193..bf89e9d7b 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_34.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_34.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_35.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_35.png index a72cf1823..40440a0e1 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_35.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_35.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_36.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_36.png index 9a13e7c67..627a02ef2 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_36.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_36.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_37.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_37.png index da3ee77f3..7cb901f41 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_37.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_37.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_38.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_38.png index 93da7f4f9..2e18adf6d 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_38.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_38.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_39.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_39.png index 7510931b4..0e8d76708 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_39.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_39.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_4.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_4.png index f99454b16..036698217 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_4.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_40.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_40.png index a17a14044..5cb229d26 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_40.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_40.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_41.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_41.png index f763540c9..b66b054b6 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_41.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_41.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_42.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_42.png index 97a829e9b..6ec37e4a6 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_42.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_42.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_43.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_43.png index 7eadf7518..efb7389df 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_43.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_43.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_44.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_44.png index 5241195d3..80a09122d 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_44.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_44.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_45.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_45.png index 2a3ea8e23..a15ddb4b6 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_45.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_45.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_46.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_46.png index f4b263b19..33602ad41 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_46.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_46.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_47.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_47.png index 1563ff39b..c5b3d4116 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_47.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_47.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_5.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_5.png index 394bb53df..e941f9963 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_5.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_6.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_6.png index 3f84ad47e..6ece9c80d 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_6.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_7.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_7.png index 8ea650ad0..63ccd3159 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_7.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_8.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_8.png index 2c8cf3f5d..e0b14160f 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_8.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_8.png differ diff --git a/assets/dolphin/external/L1_Kaiju_128x64/frame_9.png b/assets/dolphin/external/L1_Kaiju_128x64/frame_9.png index caf6a90ef..2f42f47b9 100644 Binary files a/assets/dolphin/external/L1_Kaiju_128x64/frame_9.png and b/assets/dolphin/external/L1_Kaiju_128x64/frame_9.png differ diff --git a/assets/dolphin/external/L1_Laptop_128x51/frame_0.png b/assets/dolphin/external/L1_Laptop_128x51/frame_0.png index a42e97fc4..c17941cc5 100644 Binary files a/assets/dolphin/external/L1_Laptop_128x51/frame_0.png and b/assets/dolphin/external/L1_Laptop_128x51/frame_0.png differ diff --git a/assets/dolphin/external/L1_Laptop_128x51/frame_1.png b/assets/dolphin/external/L1_Laptop_128x51/frame_1.png index 90152d2b3..80be86c65 100644 Binary files a/assets/dolphin/external/L1_Laptop_128x51/frame_1.png and b/assets/dolphin/external/L1_Laptop_128x51/frame_1.png differ diff --git a/assets/dolphin/external/L1_Laptop_128x51/frame_2.png b/assets/dolphin/external/L1_Laptop_128x51/frame_2.png index 93df45f84..c1be6d117 100644 Binary files a/assets/dolphin/external/L1_Laptop_128x51/frame_2.png and b/assets/dolphin/external/L1_Laptop_128x51/frame_2.png differ diff --git a/assets/dolphin/external/L1_Laptop_128x51/frame_3.png b/assets/dolphin/external/L1_Laptop_128x51/frame_3.png index a86b5e744..e35221cc2 100644 Binary files a/assets/dolphin/external/L1_Laptop_128x51/frame_3.png and b/assets/dolphin/external/L1_Laptop_128x51/frame_3.png differ diff --git a/assets/dolphin/external/L1_Laptop_128x51/frame_4.png b/assets/dolphin/external/L1_Laptop_128x51/frame_4.png index 8ca6f6319..85a9921ea 100644 Binary files a/assets/dolphin/external/L1_Laptop_128x51/frame_4.png and b/assets/dolphin/external/L1_Laptop_128x51/frame_4.png differ diff --git a/assets/dolphin/external/L1_Laptop_128x51/frame_5.png b/assets/dolphin/external/L1_Laptop_128x51/frame_5.png index ef1a75b90..7daaffb60 100644 Binary files a/assets/dolphin/external/L1_Laptop_128x51/frame_5.png and b/assets/dolphin/external/L1_Laptop_128x51/frame_5.png differ diff --git a/assets/dolphin/external/L1_Laptop_128x51/frame_6.png b/assets/dolphin/external/L1_Laptop_128x51/frame_6.png index 7e148697b..72e1e8efa 100644 Binary files a/assets/dolphin/external/L1_Laptop_128x51/frame_6.png and b/assets/dolphin/external/L1_Laptop_128x51/frame_6.png differ diff --git a/assets/dolphin/external/L1_Laptop_128x51/frame_7.png b/assets/dolphin/external/L1_Laptop_128x51/frame_7.png index ca19b669f..aae904928 100644 Binary files a/assets/dolphin/external/L1_Laptop_128x51/frame_7.png and b/assets/dolphin/external/L1_Laptop_128x51/frame_7.png differ diff --git a/assets/dolphin/external/L1_Leaving_sad_128x64/frame_0.png b/assets/dolphin/external/L1_Leaving_sad_128x64/frame_0.png index c7751a1d4..011570b2c 100644 Binary files a/assets/dolphin/external/L1_Leaving_sad_128x64/frame_0.png and b/assets/dolphin/external/L1_Leaving_sad_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L1_Leaving_sad_128x64/frame_1.png b/assets/dolphin/external/L1_Leaving_sad_128x64/frame_1.png index 20b3a7104..6ee8edd66 100644 Binary files a/assets/dolphin/external/L1_Leaving_sad_128x64/frame_1.png and b/assets/dolphin/external/L1_Leaving_sad_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L1_Leaving_sad_128x64/frame_10.png b/assets/dolphin/external/L1_Leaving_sad_128x64/frame_10.png index ef2ed21d6..82a990d5a 100644 Binary files a/assets/dolphin/external/L1_Leaving_sad_128x64/frame_10.png and b/assets/dolphin/external/L1_Leaving_sad_128x64/frame_10.png differ diff --git a/assets/dolphin/external/L1_Leaving_sad_128x64/frame_11.png b/assets/dolphin/external/L1_Leaving_sad_128x64/frame_11.png index 0d2610a11..36b6c7de0 100644 Binary files a/assets/dolphin/external/L1_Leaving_sad_128x64/frame_11.png and b/assets/dolphin/external/L1_Leaving_sad_128x64/frame_11.png differ diff --git a/assets/dolphin/external/L1_Leaving_sad_128x64/frame_12.png b/assets/dolphin/external/L1_Leaving_sad_128x64/frame_12.png index 1edc93480..65d285161 100644 Binary files a/assets/dolphin/external/L1_Leaving_sad_128x64/frame_12.png and b/assets/dolphin/external/L1_Leaving_sad_128x64/frame_12.png differ diff --git a/assets/dolphin/external/L1_Leaving_sad_128x64/frame_2.png b/assets/dolphin/external/L1_Leaving_sad_128x64/frame_2.png index 5752d80e6..fb44779bc 100644 Binary files a/assets/dolphin/external/L1_Leaving_sad_128x64/frame_2.png and b/assets/dolphin/external/L1_Leaving_sad_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L1_Leaving_sad_128x64/frame_3.png b/assets/dolphin/external/L1_Leaving_sad_128x64/frame_3.png index f62078f84..a05fdf825 100644 Binary files a/assets/dolphin/external/L1_Leaving_sad_128x64/frame_3.png and b/assets/dolphin/external/L1_Leaving_sad_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L1_Leaving_sad_128x64/frame_4.png b/assets/dolphin/external/L1_Leaving_sad_128x64/frame_4.png index 021e05822..8beabc6f5 100644 Binary files a/assets/dolphin/external/L1_Leaving_sad_128x64/frame_4.png and b/assets/dolphin/external/L1_Leaving_sad_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L1_Leaving_sad_128x64/frame_5.png b/assets/dolphin/external/L1_Leaving_sad_128x64/frame_5.png index d7e88112a..2bd6fec48 100644 Binary files a/assets/dolphin/external/L1_Leaving_sad_128x64/frame_5.png and b/assets/dolphin/external/L1_Leaving_sad_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L1_Leaving_sad_128x64/frame_6.png b/assets/dolphin/external/L1_Leaving_sad_128x64/frame_6.png index 142ebbca0..3e9f13a8a 100644 Binary files a/assets/dolphin/external/L1_Leaving_sad_128x64/frame_6.png and b/assets/dolphin/external/L1_Leaving_sad_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L1_Leaving_sad_128x64/frame_7.png b/assets/dolphin/external/L1_Leaving_sad_128x64/frame_7.png index 26af84948..474f90ec3 100644 Binary files a/assets/dolphin/external/L1_Leaving_sad_128x64/frame_7.png and b/assets/dolphin/external/L1_Leaving_sad_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L1_Leaving_sad_128x64/frame_8.png b/assets/dolphin/external/L1_Leaving_sad_128x64/frame_8.png index d307e7a27..6e4aea8a6 100644 Binary files a/assets/dolphin/external/L1_Leaving_sad_128x64/frame_8.png and b/assets/dolphin/external/L1_Leaving_sad_128x64/frame_8.png differ diff --git a/assets/dolphin/external/L1_Leaving_sad_128x64/frame_9.png b/assets/dolphin/external/L1_Leaving_sad_128x64/frame_9.png index 0d28a8615..b18041927 100644 Binary files a/assets/dolphin/external/L1_Leaving_sad_128x64/frame_9.png and b/assets/dolphin/external/L1_Leaving_sad_128x64/frame_9.png differ diff --git a/assets/dolphin/external/L1_Mad_fist_128x64/frame_0.png b/assets/dolphin/external/L1_Mad_fist_128x64/frame_0.png index 04aa17ac0..f41ab5ff4 100644 Binary files a/assets/dolphin/external/L1_Mad_fist_128x64/frame_0.png and b/assets/dolphin/external/L1_Mad_fist_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L1_Mad_fist_128x64/frame_1.png b/assets/dolphin/external/L1_Mad_fist_128x64/frame_1.png index d93b1f588..1430a46e1 100644 Binary files a/assets/dolphin/external/L1_Mad_fist_128x64/frame_1.png and b/assets/dolphin/external/L1_Mad_fist_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L1_Mad_fist_128x64/frame_10.png b/assets/dolphin/external/L1_Mad_fist_128x64/frame_10.png index 47185499d..4f738cda1 100644 Binary files a/assets/dolphin/external/L1_Mad_fist_128x64/frame_10.png and b/assets/dolphin/external/L1_Mad_fist_128x64/frame_10.png differ diff --git a/assets/dolphin/external/L1_Mad_fist_128x64/frame_11.png b/assets/dolphin/external/L1_Mad_fist_128x64/frame_11.png index d90fd3d5b..d8fa43eef 100644 Binary files a/assets/dolphin/external/L1_Mad_fist_128x64/frame_11.png and b/assets/dolphin/external/L1_Mad_fist_128x64/frame_11.png differ diff --git a/assets/dolphin/external/L1_Mad_fist_128x64/frame_12.png b/assets/dolphin/external/L1_Mad_fist_128x64/frame_12.png index 15ded2672..055d8a5e1 100644 Binary files a/assets/dolphin/external/L1_Mad_fist_128x64/frame_12.png and b/assets/dolphin/external/L1_Mad_fist_128x64/frame_12.png differ diff --git a/assets/dolphin/external/L1_Mad_fist_128x64/frame_13.png b/assets/dolphin/external/L1_Mad_fist_128x64/frame_13.png index 13ee0450e..449235a1e 100644 Binary files a/assets/dolphin/external/L1_Mad_fist_128x64/frame_13.png and b/assets/dolphin/external/L1_Mad_fist_128x64/frame_13.png differ diff --git a/assets/dolphin/external/L1_Mad_fist_128x64/frame_2.png b/assets/dolphin/external/L1_Mad_fist_128x64/frame_2.png index 32c0a1b9b..efd0ceab2 100644 Binary files a/assets/dolphin/external/L1_Mad_fist_128x64/frame_2.png and b/assets/dolphin/external/L1_Mad_fist_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L1_Mad_fist_128x64/frame_3.png b/assets/dolphin/external/L1_Mad_fist_128x64/frame_3.png index 93593594e..bc9310456 100644 Binary files a/assets/dolphin/external/L1_Mad_fist_128x64/frame_3.png and b/assets/dolphin/external/L1_Mad_fist_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L1_Mad_fist_128x64/frame_4.png b/assets/dolphin/external/L1_Mad_fist_128x64/frame_4.png index d6ca9b82d..1db181127 100644 Binary files a/assets/dolphin/external/L1_Mad_fist_128x64/frame_4.png and b/assets/dolphin/external/L1_Mad_fist_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L1_Mad_fist_128x64/frame_5.png b/assets/dolphin/external/L1_Mad_fist_128x64/frame_5.png index 0421d8f6f..107d82779 100644 Binary files a/assets/dolphin/external/L1_Mad_fist_128x64/frame_5.png and b/assets/dolphin/external/L1_Mad_fist_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L1_Mad_fist_128x64/frame_6.png b/assets/dolphin/external/L1_Mad_fist_128x64/frame_6.png index 17930e075..f79343f14 100644 Binary files a/assets/dolphin/external/L1_Mad_fist_128x64/frame_6.png and b/assets/dolphin/external/L1_Mad_fist_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L1_Mad_fist_128x64/frame_7.png b/assets/dolphin/external/L1_Mad_fist_128x64/frame_7.png index d4115d240..a8427f1b9 100644 Binary files a/assets/dolphin/external/L1_Mad_fist_128x64/frame_7.png and b/assets/dolphin/external/L1_Mad_fist_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L1_Mad_fist_128x64/frame_8.png b/assets/dolphin/external/L1_Mad_fist_128x64/frame_8.png index 570c8b0c4..a276c604e 100644 Binary files a/assets/dolphin/external/L1_Mad_fist_128x64/frame_8.png and b/assets/dolphin/external/L1_Mad_fist_128x64/frame_8.png differ diff --git a/assets/dolphin/external/L1_Mad_fist_128x64/frame_9.png b/assets/dolphin/external/L1_Mad_fist_128x64/frame_9.png index 2b6b6e57c..6affd4269 100644 Binary files a/assets/dolphin/external/L1_Mad_fist_128x64/frame_9.png and b/assets/dolphin/external/L1_Mad_fist_128x64/frame_9.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_0.png b/assets/dolphin/external/L1_Mods_128x64/frame_0.png index 220908495..dae494166 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_0.png and b/assets/dolphin/external/L1_Mods_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_1.png b/assets/dolphin/external/L1_Mods_128x64/frame_1.png index 9123906fb..dee80b476 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_1.png and b/assets/dolphin/external/L1_Mods_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_10.png b/assets/dolphin/external/L1_Mods_128x64/frame_10.png index e90ad5e90..d8bc4b6a1 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_10.png and b/assets/dolphin/external/L1_Mods_128x64/frame_10.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_11.png b/assets/dolphin/external/L1_Mods_128x64/frame_11.png index 031c0ad81..27f969831 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_11.png and b/assets/dolphin/external/L1_Mods_128x64/frame_11.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_12.png b/assets/dolphin/external/L1_Mods_128x64/frame_12.png index 856e068fd..f3dcb8b40 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_12.png and b/assets/dolphin/external/L1_Mods_128x64/frame_12.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_13.png b/assets/dolphin/external/L1_Mods_128x64/frame_13.png index a0366b2cf..79c049584 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_13.png and b/assets/dolphin/external/L1_Mods_128x64/frame_13.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_14.png b/assets/dolphin/external/L1_Mods_128x64/frame_14.png index 24fd557ab..0db4ceded 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_14.png and b/assets/dolphin/external/L1_Mods_128x64/frame_14.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_15.png b/assets/dolphin/external/L1_Mods_128x64/frame_15.png index 3bf1d3ed2..647afd6a3 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_15.png and b/assets/dolphin/external/L1_Mods_128x64/frame_15.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_16.png b/assets/dolphin/external/L1_Mods_128x64/frame_16.png index f0b44898f..978f9716b 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_16.png and b/assets/dolphin/external/L1_Mods_128x64/frame_16.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_17.png b/assets/dolphin/external/L1_Mods_128x64/frame_17.png index c98c70c91..8f8e0ce52 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_17.png and b/assets/dolphin/external/L1_Mods_128x64/frame_17.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_18.png b/assets/dolphin/external/L1_Mods_128x64/frame_18.png index 4f7b7ae82..bb934d7da 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_18.png and b/assets/dolphin/external/L1_Mods_128x64/frame_18.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_19.png b/assets/dolphin/external/L1_Mods_128x64/frame_19.png index b3ad6700c..ff8a13ae4 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_19.png and b/assets/dolphin/external/L1_Mods_128x64/frame_19.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_2.png b/assets/dolphin/external/L1_Mods_128x64/frame_2.png index c4aac4b91..c0a3ced72 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_2.png and b/assets/dolphin/external/L1_Mods_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_20.png b/assets/dolphin/external/L1_Mods_128x64/frame_20.png index ea2eae4d7..2096e47e1 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_20.png and b/assets/dolphin/external/L1_Mods_128x64/frame_20.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_21.png b/assets/dolphin/external/L1_Mods_128x64/frame_21.png index 00a7a6e99..a6c655ff4 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_21.png and b/assets/dolphin/external/L1_Mods_128x64/frame_21.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_22.png b/assets/dolphin/external/L1_Mods_128x64/frame_22.png index 137d5ddf6..69995b037 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_22.png and b/assets/dolphin/external/L1_Mods_128x64/frame_22.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_23.png b/assets/dolphin/external/L1_Mods_128x64/frame_23.png index 89690fc03..2440f0b98 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_23.png and b/assets/dolphin/external/L1_Mods_128x64/frame_23.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_24.png b/assets/dolphin/external/L1_Mods_128x64/frame_24.png index 53d7b07a5..c0a282460 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_24.png and b/assets/dolphin/external/L1_Mods_128x64/frame_24.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_25.png b/assets/dolphin/external/L1_Mods_128x64/frame_25.png index 2838804e5..f15cb8032 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_25.png and b/assets/dolphin/external/L1_Mods_128x64/frame_25.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_26.png b/assets/dolphin/external/L1_Mods_128x64/frame_26.png index 2af49cf17..b773ccc9d 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_26.png and b/assets/dolphin/external/L1_Mods_128x64/frame_26.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_27.png b/assets/dolphin/external/L1_Mods_128x64/frame_27.png index 7dc44d061..743355326 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_27.png and b/assets/dolphin/external/L1_Mods_128x64/frame_27.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_28.png b/assets/dolphin/external/L1_Mods_128x64/frame_28.png index 87df75ff7..8840bbcea 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_28.png and b/assets/dolphin/external/L1_Mods_128x64/frame_28.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_29.png b/assets/dolphin/external/L1_Mods_128x64/frame_29.png index 2fdb9d736..762c6e0d4 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_29.png and b/assets/dolphin/external/L1_Mods_128x64/frame_29.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_3.png b/assets/dolphin/external/L1_Mods_128x64/frame_3.png index 1b0e77426..9bfa51cce 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_3.png and b/assets/dolphin/external/L1_Mods_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_30.png b/assets/dolphin/external/L1_Mods_128x64/frame_30.png index 785f19fd0..159c29d12 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_30.png and b/assets/dolphin/external/L1_Mods_128x64/frame_30.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_31.png b/assets/dolphin/external/L1_Mods_128x64/frame_31.png index 36310f705..2071a71b3 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_31.png and b/assets/dolphin/external/L1_Mods_128x64/frame_31.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_32.png b/assets/dolphin/external/L1_Mods_128x64/frame_32.png index 92db8f024..fb4d154a8 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_32.png and b/assets/dolphin/external/L1_Mods_128x64/frame_32.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_33.png b/assets/dolphin/external/L1_Mods_128x64/frame_33.png index 768030b3c..6fa9ba366 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_33.png and b/assets/dolphin/external/L1_Mods_128x64/frame_33.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_34.png b/assets/dolphin/external/L1_Mods_128x64/frame_34.png index 12f22abdb..3a1095e67 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_34.png and b/assets/dolphin/external/L1_Mods_128x64/frame_34.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_35.png b/assets/dolphin/external/L1_Mods_128x64/frame_35.png index 9fca976de..08c620cbe 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_35.png and b/assets/dolphin/external/L1_Mods_128x64/frame_35.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_36.png b/assets/dolphin/external/L1_Mods_128x64/frame_36.png index 4b2ab5863..526af8e6f 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_36.png and b/assets/dolphin/external/L1_Mods_128x64/frame_36.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_37.png b/assets/dolphin/external/L1_Mods_128x64/frame_37.png index 69c709adc..364a01470 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_37.png and b/assets/dolphin/external/L1_Mods_128x64/frame_37.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_38.png b/assets/dolphin/external/L1_Mods_128x64/frame_38.png index 13caae7ca..d076f9036 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_38.png and b/assets/dolphin/external/L1_Mods_128x64/frame_38.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_39.png b/assets/dolphin/external/L1_Mods_128x64/frame_39.png index b1d1e8bfe..fb4d513e5 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_39.png and b/assets/dolphin/external/L1_Mods_128x64/frame_39.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_4.png b/assets/dolphin/external/L1_Mods_128x64/frame_4.png index 45e47de12..9f109397b 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_4.png and b/assets/dolphin/external/L1_Mods_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_40.png b/assets/dolphin/external/L1_Mods_128x64/frame_40.png index acf000827..9110b8e79 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_40.png and b/assets/dolphin/external/L1_Mods_128x64/frame_40.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_41.png b/assets/dolphin/external/L1_Mods_128x64/frame_41.png index b6c6fbb19..78f18d10d 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_41.png and b/assets/dolphin/external/L1_Mods_128x64/frame_41.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_42.png b/assets/dolphin/external/L1_Mods_128x64/frame_42.png index 7d2dcda5d..8cf002760 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_42.png and b/assets/dolphin/external/L1_Mods_128x64/frame_42.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_43.png b/assets/dolphin/external/L1_Mods_128x64/frame_43.png index 461270ba4..e85358c51 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_43.png and b/assets/dolphin/external/L1_Mods_128x64/frame_43.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_44.png b/assets/dolphin/external/L1_Mods_128x64/frame_44.png index b018a94c1..51e4f2c12 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_44.png and b/assets/dolphin/external/L1_Mods_128x64/frame_44.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_45.png b/assets/dolphin/external/L1_Mods_128x64/frame_45.png index fa2b303cc..732869454 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_45.png and b/assets/dolphin/external/L1_Mods_128x64/frame_45.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_46.png b/assets/dolphin/external/L1_Mods_128x64/frame_46.png index ed38122f5..a4a4953f6 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_46.png and b/assets/dolphin/external/L1_Mods_128x64/frame_46.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_47.png b/assets/dolphin/external/L1_Mods_128x64/frame_47.png index 38610bb4b..cb28e28f1 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_47.png and b/assets/dolphin/external/L1_Mods_128x64/frame_47.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_48.png b/assets/dolphin/external/L1_Mods_128x64/frame_48.png index 7f6b4b29a..900a3d7c5 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_48.png and b/assets/dolphin/external/L1_Mods_128x64/frame_48.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_5.png b/assets/dolphin/external/L1_Mods_128x64/frame_5.png index 7c293b485..3ac80fca4 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_5.png and b/assets/dolphin/external/L1_Mods_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_6.png b/assets/dolphin/external/L1_Mods_128x64/frame_6.png index e72e7a30e..063a87b2e 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_6.png and b/assets/dolphin/external/L1_Mods_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_7.png b/assets/dolphin/external/L1_Mods_128x64/frame_7.png index 5c840d6f6..f65df4778 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_7.png and b/assets/dolphin/external/L1_Mods_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_8.png b/assets/dolphin/external/L1_Mods_128x64/frame_8.png index f689f190c..b6898b1bc 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_8.png and b/assets/dolphin/external/L1_Mods_128x64/frame_8.png differ diff --git a/assets/dolphin/external/L1_Mods_128x64/frame_9.png b/assets/dolphin/external/L1_Mods_128x64/frame_9.png index 628394e57..854a2edec 100644 Binary files a/assets/dolphin/external/L1_Mods_128x64/frame_9.png and b/assets/dolphin/external/L1_Mods_128x64/frame_9.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_0.png b/assets/dolphin/external/L1_My_dude_128x64/frame_0.png index bf07d03d6..4706786b7 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_0.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_1.png b/assets/dolphin/external/L1_My_dude_128x64/frame_1.png index 4402654c7..e81a3eae7 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_1.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_10.png b/assets/dolphin/external/L1_My_dude_128x64/frame_10.png index 10dabe4c5..7a6f765de 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_10.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_10.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_11.png b/assets/dolphin/external/L1_My_dude_128x64/frame_11.png index 878712fe2..2486f1a8b 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_11.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_11.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_12.png b/assets/dolphin/external/L1_My_dude_128x64/frame_12.png index 19fc985ac..d01bb39f5 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_12.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_12.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_13.png b/assets/dolphin/external/L1_My_dude_128x64/frame_13.png index 39172f26f..2f4cb5987 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_13.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_13.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_14.png b/assets/dolphin/external/L1_My_dude_128x64/frame_14.png index 9a3a84fff..c8b3def2a 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_14.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_14.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_15.png b/assets/dolphin/external/L1_My_dude_128x64/frame_15.png index 2472c2729..e545002bd 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_15.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_15.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_16.png b/assets/dolphin/external/L1_My_dude_128x64/frame_16.png index 4940aef67..8e906e4f4 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_16.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_16.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_17.png b/assets/dolphin/external/L1_My_dude_128x64/frame_17.png index fd910ce5a..56765ecb8 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_17.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_17.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_18.png b/assets/dolphin/external/L1_My_dude_128x64/frame_18.png index ed33f18a7..1deb8d82f 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_18.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_18.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_19.png b/assets/dolphin/external/L1_My_dude_128x64/frame_19.png index d602a01d5..ac288ba8a 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_19.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_19.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_2.png b/assets/dolphin/external/L1_My_dude_128x64/frame_2.png index b680b4ae0..7bee6a8ed 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_2.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_20.png b/assets/dolphin/external/L1_My_dude_128x64/frame_20.png index 2dfa931f2..e57cd0f98 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_20.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_20.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_21.png b/assets/dolphin/external/L1_My_dude_128x64/frame_21.png index 272064d90..36ac0f843 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_21.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_21.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_22.png b/assets/dolphin/external/L1_My_dude_128x64/frame_22.png index 35d0149ad..007cae6b7 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_22.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_22.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_23.png b/assets/dolphin/external/L1_My_dude_128x64/frame_23.png index 83d02ef88..a446291b2 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_23.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_23.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_24.png b/assets/dolphin/external/L1_My_dude_128x64/frame_24.png index f3ac44178..2191b5e70 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_24.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_24.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_25.png b/assets/dolphin/external/L1_My_dude_128x64/frame_25.png index 832c2bde9..e30f6f4d0 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_25.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_25.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_26.png b/assets/dolphin/external/L1_My_dude_128x64/frame_26.png index 3836a3b01..06cd12d2c 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_26.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_26.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_27.png b/assets/dolphin/external/L1_My_dude_128x64/frame_27.png index ff621b73e..1abb14dbd 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_27.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_27.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_28.png b/assets/dolphin/external/L1_My_dude_128x64/frame_28.png index 94e05f94d..2f9f7106e 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_28.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_28.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_29.png b/assets/dolphin/external/L1_My_dude_128x64/frame_29.png index 1ce384b16..dffa2d7c5 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_29.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_29.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_3.png b/assets/dolphin/external/L1_My_dude_128x64/frame_3.png index a5056eb4b..314efc632 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_3.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_30.png b/assets/dolphin/external/L1_My_dude_128x64/frame_30.png index 8d42b8b48..52b8d35f0 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_30.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_30.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_31.png b/assets/dolphin/external/L1_My_dude_128x64/frame_31.png index ac926d7be..6c282c0af 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_31.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_31.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_32.png b/assets/dolphin/external/L1_My_dude_128x64/frame_32.png index 35070eb6b..1d1f631b0 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_32.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_32.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_33.png b/assets/dolphin/external/L1_My_dude_128x64/frame_33.png index a6c973f67..4376fe29f 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_33.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_33.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_34.png b/assets/dolphin/external/L1_My_dude_128x64/frame_34.png index 3f9407f38..d431b9090 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_34.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_34.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_35.png b/assets/dolphin/external/L1_My_dude_128x64/frame_35.png index 6059e00d5..77085b8a6 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_35.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_35.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_36.png b/assets/dolphin/external/L1_My_dude_128x64/frame_36.png index d2cd0c970..f9d8b6ebf 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_36.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_36.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_37.png b/assets/dolphin/external/L1_My_dude_128x64/frame_37.png index e60fd08de..18080af54 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_37.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_37.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_38.png b/assets/dolphin/external/L1_My_dude_128x64/frame_38.png index 70e56b168..5ccdcce39 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_38.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_38.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_39.png b/assets/dolphin/external/L1_My_dude_128x64/frame_39.png index 450b4d4f6..cc3b2c5e3 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_39.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_39.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_4.png b/assets/dolphin/external/L1_My_dude_128x64/frame_4.png index 2d9f4e963..4b7361a42 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_4.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_40.png b/assets/dolphin/external/L1_My_dude_128x64/frame_40.png index 369200345..ac0c42834 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_40.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_40.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_41.png b/assets/dolphin/external/L1_My_dude_128x64/frame_41.png index e0f882268..bb200d9a3 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_41.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_41.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_42.png b/assets/dolphin/external/L1_My_dude_128x64/frame_42.png index a8a23536a..46f9d7dda 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_42.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_42.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_43.png b/assets/dolphin/external/L1_My_dude_128x64/frame_43.png index 6a402b350..1dcdd52f4 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_43.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_43.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_44.png b/assets/dolphin/external/L1_My_dude_128x64/frame_44.png index f425bcc17..2d3431825 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_44.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_44.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_45.png b/assets/dolphin/external/L1_My_dude_128x64/frame_45.png index b0ea1a7e7..3c27a8d1f 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_45.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_45.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_46.png b/assets/dolphin/external/L1_My_dude_128x64/frame_46.png index 3113ff2e6..532907537 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_46.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_46.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_47.png b/assets/dolphin/external/L1_My_dude_128x64/frame_47.png index 87403c610..d4e5ccfe2 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_47.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_47.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_48.png b/assets/dolphin/external/L1_My_dude_128x64/frame_48.png index 2734e2fcd..30848e939 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_48.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_48.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_5.png b/assets/dolphin/external/L1_My_dude_128x64/frame_5.png index df2255949..a27a74b00 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_5.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_6.png b/assets/dolphin/external/L1_My_dude_128x64/frame_6.png index 4c00552ea..34233f5bb 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_6.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_7.png b/assets/dolphin/external/L1_My_dude_128x64/frame_7.png index 970380940..f21b4f406 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_7.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_8.png b/assets/dolphin/external/L1_My_dude_128x64/frame_8.png index 86e41e913..1f574da94 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_8.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_8.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_9.png b/assets/dolphin/external/L1_My_dude_128x64/frame_9.png index 4334eefaf..5e75e2dff 100644 Binary files a/assets/dolphin/external/L1_My_dude_128x64/frame_9.png and b/assets/dolphin/external/L1_My_dude_128x64/frame_9.png differ diff --git a/assets/dolphin/external/L1_Painting_128x64/frame_0.png b/assets/dolphin/external/L1_Painting_128x64/frame_0.png index b2f9bc775..154a85ffb 100644 Binary files a/assets/dolphin/external/L1_Painting_128x64/frame_0.png and b/assets/dolphin/external/L1_Painting_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L1_Painting_128x64/frame_1.png b/assets/dolphin/external/L1_Painting_128x64/frame_1.png index 02ac533ce..e52dfd628 100644 Binary files a/assets/dolphin/external/L1_Painting_128x64/frame_1.png and b/assets/dolphin/external/L1_Painting_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L1_Painting_128x64/frame_10.png b/assets/dolphin/external/L1_Painting_128x64/frame_10.png index ae3148c32..39389a64f 100644 Binary files a/assets/dolphin/external/L1_Painting_128x64/frame_10.png and b/assets/dolphin/external/L1_Painting_128x64/frame_10.png differ diff --git a/assets/dolphin/external/L1_Painting_128x64/frame_11.png b/assets/dolphin/external/L1_Painting_128x64/frame_11.png index 89d003d07..e6ea79c37 100644 Binary files a/assets/dolphin/external/L1_Painting_128x64/frame_11.png and b/assets/dolphin/external/L1_Painting_128x64/frame_11.png differ diff --git a/assets/dolphin/external/L1_Painting_128x64/frame_2.png b/assets/dolphin/external/L1_Painting_128x64/frame_2.png index 8bfe6b33c..302d5be61 100644 Binary files a/assets/dolphin/external/L1_Painting_128x64/frame_2.png and b/assets/dolphin/external/L1_Painting_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L1_Painting_128x64/frame_3.png b/assets/dolphin/external/L1_Painting_128x64/frame_3.png index 1c6fc2144..6227c4089 100644 Binary files a/assets/dolphin/external/L1_Painting_128x64/frame_3.png and b/assets/dolphin/external/L1_Painting_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L1_Painting_128x64/frame_4.png b/assets/dolphin/external/L1_Painting_128x64/frame_4.png index d39cddea1..8d76d9d0d 100644 Binary files a/assets/dolphin/external/L1_Painting_128x64/frame_4.png and b/assets/dolphin/external/L1_Painting_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L1_Painting_128x64/frame_5.png b/assets/dolphin/external/L1_Painting_128x64/frame_5.png index 4f21a268a..5e562ce05 100644 Binary files a/assets/dolphin/external/L1_Painting_128x64/frame_5.png and b/assets/dolphin/external/L1_Painting_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L1_Painting_128x64/frame_6.png b/assets/dolphin/external/L1_Painting_128x64/frame_6.png index 3f492eab5..9284cbef9 100644 Binary files a/assets/dolphin/external/L1_Painting_128x64/frame_6.png and b/assets/dolphin/external/L1_Painting_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L1_Painting_128x64/frame_7.png b/assets/dolphin/external/L1_Painting_128x64/frame_7.png index 336cffcb4..8212e629c 100644 Binary files a/assets/dolphin/external/L1_Painting_128x64/frame_7.png and b/assets/dolphin/external/L1_Painting_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L1_Painting_128x64/frame_8.png b/assets/dolphin/external/L1_Painting_128x64/frame_8.png index a44a7315d..f13bf906c 100644 Binary files a/assets/dolphin/external/L1_Painting_128x64/frame_8.png and b/assets/dolphin/external/L1_Painting_128x64/frame_8.png differ diff --git a/assets/dolphin/external/L1_Painting_128x64/frame_9.png b/assets/dolphin/external/L1_Painting_128x64/frame_9.png index 7cd425291..65c881627 100644 Binary files a/assets/dolphin/external/L1_Painting_128x64/frame_9.png and b/assets/dolphin/external/L1_Painting_128x64/frame_9.png differ diff --git a/assets/dolphin/external/L1_Read_books_128x64/frame_0.png b/assets/dolphin/external/L1_Read_books_128x64/frame_0.png index fbf265286..240fc15d5 100644 Binary files a/assets/dolphin/external/L1_Read_books_128x64/frame_0.png and b/assets/dolphin/external/L1_Read_books_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L1_Read_books_128x64/frame_1.png b/assets/dolphin/external/L1_Read_books_128x64/frame_1.png index be9c5dc15..7037de7ba 100644 Binary files a/assets/dolphin/external/L1_Read_books_128x64/frame_1.png and b/assets/dolphin/external/L1_Read_books_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L1_Read_books_128x64/frame_2.png b/assets/dolphin/external/L1_Read_books_128x64/frame_2.png index eb8075ecb..627edfaa4 100644 Binary files a/assets/dolphin/external/L1_Read_books_128x64/frame_2.png and b/assets/dolphin/external/L1_Read_books_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L1_Read_books_128x64/frame_3.png b/assets/dolphin/external/L1_Read_books_128x64/frame_3.png index 0f1fd5c52..babab2e47 100644 Binary files a/assets/dolphin/external/L1_Read_books_128x64/frame_3.png and b/assets/dolphin/external/L1_Read_books_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L1_Read_books_128x64/frame_4.png b/assets/dolphin/external/L1_Read_books_128x64/frame_4.png index dd2d918af..1a3f38e48 100644 Binary files a/assets/dolphin/external/L1_Read_books_128x64/frame_4.png and b/assets/dolphin/external/L1_Read_books_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L1_Read_books_128x64/frame_5.png b/assets/dolphin/external/L1_Read_books_128x64/frame_5.png index bfcc7bcd2..5f864b0d8 100644 Binary files a/assets/dolphin/external/L1_Read_books_128x64/frame_5.png and b/assets/dolphin/external/L1_Read_books_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L1_Read_books_128x64/frame_6.png b/assets/dolphin/external/L1_Read_books_128x64/frame_6.png index eabe9def3..aded14709 100644 Binary files a/assets/dolphin/external/L1_Read_books_128x64/frame_6.png and b/assets/dolphin/external/L1_Read_books_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L1_Read_books_128x64/frame_7.png b/assets/dolphin/external/L1_Read_books_128x64/frame_7.png index 3ff0aee0c..9540789e7 100644 Binary files a/assets/dolphin/external/L1_Read_books_128x64/frame_7.png and b/assets/dolphin/external/L1_Read_books_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L1_Read_books_128x64/frame_8.png b/assets/dolphin/external/L1_Read_books_128x64/frame_8.png index ce663f75f..2d87b962c 100644 Binary files a/assets/dolphin/external/L1_Read_books_128x64/frame_8.png and b/assets/dolphin/external/L1_Read_books_128x64/frame_8.png differ diff --git a/assets/dolphin/external/L1_Recording_128x51/frame_0.png b/assets/dolphin/external/L1_Recording_128x51/frame_0.png index ed0f030b8..e1361d632 100644 Binary files a/assets/dolphin/external/L1_Recording_128x51/frame_0.png and b/assets/dolphin/external/L1_Recording_128x51/frame_0.png differ diff --git a/assets/dolphin/external/L1_Recording_128x51/frame_1.png b/assets/dolphin/external/L1_Recording_128x51/frame_1.png index f3b3f8a97..0b549c648 100644 Binary files a/assets/dolphin/external/L1_Recording_128x51/frame_1.png and b/assets/dolphin/external/L1_Recording_128x51/frame_1.png differ diff --git a/assets/dolphin/external/L1_Recording_128x51/frame_10.png b/assets/dolphin/external/L1_Recording_128x51/frame_10.png index a474c2147..e45ac86be 100644 Binary files a/assets/dolphin/external/L1_Recording_128x51/frame_10.png and b/assets/dolphin/external/L1_Recording_128x51/frame_10.png differ diff --git a/assets/dolphin/external/L1_Recording_128x51/frame_11.png b/assets/dolphin/external/L1_Recording_128x51/frame_11.png index cf654afb2..487e5ea4b 100644 Binary files a/assets/dolphin/external/L1_Recording_128x51/frame_11.png and b/assets/dolphin/external/L1_Recording_128x51/frame_11.png differ diff --git a/assets/dolphin/external/L1_Recording_128x51/frame_2.png b/assets/dolphin/external/L1_Recording_128x51/frame_2.png index f61e59efd..2901debc4 100644 Binary files a/assets/dolphin/external/L1_Recording_128x51/frame_2.png and b/assets/dolphin/external/L1_Recording_128x51/frame_2.png differ diff --git a/assets/dolphin/external/L1_Recording_128x51/frame_3.png b/assets/dolphin/external/L1_Recording_128x51/frame_3.png index 87e297b2a..c0e2388b7 100644 Binary files a/assets/dolphin/external/L1_Recording_128x51/frame_3.png and b/assets/dolphin/external/L1_Recording_128x51/frame_3.png differ diff --git a/assets/dolphin/external/L1_Recording_128x51/frame_4.png b/assets/dolphin/external/L1_Recording_128x51/frame_4.png index 62428a405..c81f90539 100644 Binary files a/assets/dolphin/external/L1_Recording_128x51/frame_4.png and b/assets/dolphin/external/L1_Recording_128x51/frame_4.png differ diff --git a/assets/dolphin/external/L1_Recording_128x51/frame_5.png b/assets/dolphin/external/L1_Recording_128x51/frame_5.png index 93953024a..22006b552 100644 Binary files a/assets/dolphin/external/L1_Recording_128x51/frame_5.png and b/assets/dolphin/external/L1_Recording_128x51/frame_5.png differ diff --git a/assets/dolphin/external/L1_Recording_128x51/frame_6.png b/assets/dolphin/external/L1_Recording_128x51/frame_6.png index 942f082b8..aecd99f1a 100644 Binary files a/assets/dolphin/external/L1_Recording_128x51/frame_6.png and b/assets/dolphin/external/L1_Recording_128x51/frame_6.png differ diff --git a/assets/dolphin/external/L1_Recording_128x51/frame_7.png b/assets/dolphin/external/L1_Recording_128x51/frame_7.png index 84ce00d23..c7b305372 100644 Binary files a/assets/dolphin/external/L1_Recording_128x51/frame_7.png and b/assets/dolphin/external/L1_Recording_128x51/frame_7.png differ diff --git a/assets/dolphin/external/L1_Recording_128x51/frame_8.png b/assets/dolphin/external/L1_Recording_128x51/frame_8.png index f6f45552b..6fac0a661 100644 Binary files a/assets/dolphin/external/L1_Recording_128x51/frame_8.png and b/assets/dolphin/external/L1_Recording_128x51/frame_8.png differ diff --git a/assets/dolphin/external/L1_Recording_128x51/frame_9.png b/assets/dolphin/external/L1_Recording_128x51/frame_9.png index dcd3aa0b9..448266cd2 100644 Binary files a/assets/dolphin/external/L1_Recording_128x51/frame_9.png and b/assets/dolphin/external/L1_Recording_128x51/frame_9.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_0.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_0.png index 71e85fe8f..36e5de4c9 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_0.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_1.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_1.png index 31ab932b9..488fe0b7f 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_1.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_10.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_10.png index da8f13680..16f533859 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_10.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_10.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_11.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_11.png index 9c87945b5..756edb318 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_11.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_11.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_12.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_12.png index 52ecb01c1..0fd1b1923 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_12.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_12.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_13.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_13.png index 165b0635a..f5c1aafed 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_13.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_13.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_14.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_14.png index 3ad1f1c2d..4604cdd8b 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_14.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_14.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_15.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_15.png index dace07e83..55cc941a4 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_15.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_15.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_16.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_16.png index 2f2321888..98ad085ba 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_16.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_16.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_17.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_17.png index ea67b3645..960144d83 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_17.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_17.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_18.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_18.png index e4526da94..f749b7016 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_18.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_18.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_19.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_19.png index b6e3de1ac..39ce84076 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_19.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_19.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_2.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_2.png index a76a00022..4ec651e93 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_2.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_20.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_20.png index b33656867..acc8a1953 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_20.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_20.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_21.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_21.png index 6048810f0..1a92c7497 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_21.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_21.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_22.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_22.png index 657788f2b..0b901927f 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_22.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_22.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_23.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_23.png index 852e778bf..9d08f7fcc 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_23.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_23.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_24.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_24.png index d8497ee6a..fb33a6096 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_24.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_24.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_25.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_25.png index d647aae1b..c037fa722 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_25.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_25.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_26.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_26.png index 83bc94316..2cd08ec11 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_26.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_26.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_27.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_27.png index 9f4e0ce7b..99cff1546 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_27.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_27.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_28.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_28.png index 894394ab3..21392b7bf 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_28.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_28.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_29.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_29.png index 63babe793..a3f0884d7 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_29.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_29.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_3.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_3.png index 630f42f2e..0c6b92d80 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_3.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_30.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_30.png index d062254d9..a713249b5 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_30.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_30.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_31.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_31.png index 01ebecda7..b665a5f73 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_31.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_31.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_32.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_32.png index a66d6a42d..b59586e1d 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_32.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_32.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_33.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_33.png index e80a66743..49ba8f87c 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_33.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_33.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_34.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_34.png index cea25e209..732f631b7 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_34.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_34.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_35.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_35.png index 56e05f8f9..73fce28e1 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_35.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_35.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_36.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_36.png index 8e72a7c39..79012bb33 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_36.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_36.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_37.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_37.png index 9f20081e5..010a65723 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_37.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_37.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_38.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_38.png index 39e620954..2c2968c9f 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_38.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_38.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_39.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_39.png index febe3bf0b..df3acd8c9 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_39.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_39.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_4.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_4.png index 7377c6080..711f8f7a9 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_4.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_40.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_40.png index 2540fd383..2d4e76805 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_40.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_40.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_41.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_41.png index 63106c87a..74eb8a616 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_41.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_41.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_42.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_42.png index 21038b47a..fc7749ba9 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_42.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_42.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_43.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_43.png index 09309607c..28f4f08fa 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_43.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_43.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_44.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_44.png index 2d4b51225..2a74b2672 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_44.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_44.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_45.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_45.png index 0501b735a..aa8fa6d9a 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_45.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_45.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_46.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_46.png index 1edca6aed..e2125cace 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_46.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_46.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_47.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_47.png index 467fe93e0..b8262652e 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_47.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_47.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_48.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_48.png index fb2c54aa9..14e24f0ce 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_48.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_48.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_49.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_49.png index 74cd345fa..20239a207 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_49.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_49.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_5.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_5.png index 70ed4f559..2da816601 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_5.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_50.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_50.png index 32221d347..fc626f579 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_50.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_50.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_51.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_51.png index a81457ddc..cf189de57 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_51.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_51.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_52.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_52.png index 3fc75d870..e64fded4c 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_52.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_52.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_53.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_53.png index 2e4528c73..01475f218 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_53.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_53.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_54.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_54.png index abab31964..07e8a61f0 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_54.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_54.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_55.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_55.png index dfa5312f5..67ad03e66 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_55.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_55.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_56.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_56.png index 59a194b14..ab2ca4b9a 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_56.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_56.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_57.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_57.png index d142a38db..e4893fd0c 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_57.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_57.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_58.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_58.png index d6a66da8b..52f0ed99f 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_58.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_58.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_59.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_59.png index 4ab56d31e..95542d4a2 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_59.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_59.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_6.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_6.png index 7d4f0684e..a28e22e4f 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_6.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_60.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_60.png index 0cb8722e3..5b311fbe6 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_60.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_60.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_61.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_61.png index 7da7d1adf..ef4d9db7e 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_61.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_61.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_62.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_62.png index 1bfd8d303..c6d519fb4 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_62.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_62.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_7.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_7.png index 0ff0f5a3f..4e363367e 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_7.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_8.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_8.png index 698776737..53a4652de 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_8.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_8.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_9.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_9.png index 606272119..24d0fc41c 100644 Binary files a/assets/dolphin/external/L1_Sad_song_128x64/frame_9.png and b/assets/dolphin/external/L1_Sad_song_128x64/frame_9.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_0.png b/assets/dolphin/external/L1_Senpai_128x64/frame_0.png index ed37723ac..7390c84e8 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_0.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_1.png b/assets/dolphin/external/L1_Senpai_128x64/frame_1.png index ad708ee43..bf14f9319 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_1.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_10.png b/assets/dolphin/external/L1_Senpai_128x64/frame_10.png index e385018bf..db0766f66 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_10.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_10.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_11.png b/assets/dolphin/external/L1_Senpai_128x64/frame_11.png index 553a979be..92ad6d095 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_11.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_11.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_12.png b/assets/dolphin/external/L1_Senpai_128x64/frame_12.png index 9f8ca7e9b..02b5c78ff 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_12.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_12.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_13.png b/assets/dolphin/external/L1_Senpai_128x64/frame_13.png index a996443fe..b8537f4bf 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_13.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_13.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_14.png b/assets/dolphin/external/L1_Senpai_128x64/frame_14.png index 628d58b93..3e51ddea0 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_14.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_14.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_15.png b/assets/dolphin/external/L1_Senpai_128x64/frame_15.png index cc8431ade..a86e54c3f 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_15.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_15.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_16.png b/assets/dolphin/external/L1_Senpai_128x64/frame_16.png index 3ec372798..230ae8d89 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_16.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_16.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_17.png b/assets/dolphin/external/L1_Senpai_128x64/frame_17.png index 11b247eca..e92acac9c 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_17.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_17.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_18.png b/assets/dolphin/external/L1_Senpai_128x64/frame_18.png index bb1504133..47b716ef7 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_18.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_18.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_19.png b/assets/dolphin/external/L1_Senpai_128x64/frame_19.png index f953c8ef1..4166b75c0 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_19.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_19.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_2.png b/assets/dolphin/external/L1_Senpai_128x64/frame_2.png index 36c3b4abe..337bc2dd3 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_2.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_20.png b/assets/dolphin/external/L1_Senpai_128x64/frame_20.png index d683b9f62..9974b362d 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_20.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_20.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_21.png b/assets/dolphin/external/L1_Senpai_128x64/frame_21.png index 66cbfe1d8..f5d661ea4 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_21.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_21.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_22.png b/assets/dolphin/external/L1_Senpai_128x64/frame_22.png index dd241d24a..8517b6089 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_22.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_22.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_23.png b/assets/dolphin/external/L1_Senpai_128x64/frame_23.png index 944bdc74e..fd5d53b27 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_23.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_23.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_24.png b/assets/dolphin/external/L1_Senpai_128x64/frame_24.png index 3f445593a..7e7d008bc 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_24.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_24.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_25.png b/assets/dolphin/external/L1_Senpai_128x64/frame_25.png index ea7823bd7..5f1ea16ef 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_25.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_25.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_26.png b/assets/dolphin/external/L1_Senpai_128x64/frame_26.png index 0b378fbcc..d916f3f05 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_26.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_26.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_27.png b/assets/dolphin/external/L1_Senpai_128x64/frame_27.png index 66eec542a..6622bcdeb 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_27.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_27.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_28.png b/assets/dolphin/external/L1_Senpai_128x64/frame_28.png index 1e232ba91..24e579be1 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_28.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_28.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_29.png b/assets/dolphin/external/L1_Senpai_128x64/frame_29.png index e2767bd65..641cd9980 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_29.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_29.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_3.png b/assets/dolphin/external/L1_Senpai_128x64/frame_3.png index 9a3c13f66..c610eddcf 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_3.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_30.png b/assets/dolphin/external/L1_Senpai_128x64/frame_30.png index 36d1212be..b43b475a0 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_30.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_30.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_31.png b/assets/dolphin/external/L1_Senpai_128x64/frame_31.png index 037bdc8ed..28b2f921b 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_31.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_31.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_32.png b/assets/dolphin/external/L1_Senpai_128x64/frame_32.png index 91ce18869..819ae205e 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_32.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_32.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_33.png b/assets/dolphin/external/L1_Senpai_128x64/frame_33.png index e3e7799db..0e43a4987 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_33.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_33.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_34.png b/assets/dolphin/external/L1_Senpai_128x64/frame_34.png index a28aac4e0..53c2ce75c 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_34.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_34.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_35.png b/assets/dolphin/external/L1_Senpai_128x64/frame_35.png index 04f8c1a7f..693896bac 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_35.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_35.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_4.png b/assets/dolphin/external/L1_Senpai_128x64/frame_4.png index d065b77a1..966e60681 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_4.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_5.png b/assets/dolphin/external/L1_Senpai_128x64/frame_5.png index 7a111afd0..838f46432 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_5.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_6.png b/assets/dolphin/external/L1_Senpai_128x64/frame_6.png index 318c7eca0..f5e811188 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_6.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_7.png b/assets/dolphin/external/L1_Senpai_128x64/frame_7.png index b56b995dc..aabcd529e 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_7.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_8.png b/assets/dolphin/external/L1_Senpai_128x64/frame_8.png index 6c4b87570..4c18a154c 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_8.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_8.png differ diff --git a/assets/dolphin/external/L1_Senpai_128x64/frame_9.png b/assets/dolphin/external/L1_Senpai_128x64/frame_9.png index 00b02330e..577207e5c 100644 Binary files a/assets/dolphin/external/L1_Senpai_128x64/frame_9.png and b/assets/dolphin/external/L1_Senpai_128x64/frame_9.png differ diff --git a/assets/dolphin/external/L1_Sleep_128x64/frame_0.png b/assets/dolphin/external/L1_Sleep_128x64/frame_0.png index 851f1d01d..69d0d671e 100644 Binary files a/assets/dolphin/external/L1_Sleep_128x64/frame_0.png and b/assets/dolphin/external/L1_Sleep_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L1_Sleep_128x64/frame_1.png b/assets/dolphin/external/L1_Sleep_128x64/frame_1.png index 89b40b36f..c29188dc4 100644 Binary files a/assets/dolphin/external/L1_Sleep_128x64/frame_1.png and b/assets/dolphin/external/L1_Sleep_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L1_Sleep_128x64/frame_2.png b/assets/dolphin/external/L1_Sleep_128x64/frame_2.png index 70ad96dde..20f3709d2 100644 Binary files a/assets/dolphin/external/L1_Sleep_128x64/frame_2.png and b/assets/dolphin/external/L1_Sleep_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L1_Sleep_128x64/frame_3.png b/assets/dolphin/external/L1_Sleep_128x64/frame_3.png index 03b2f529a..83792b943 100644 Binary files a/assets/dolphin/external/L1_Sleep_128x64/frame_3.png and b/assets/dolphin/external/L1_Sleep_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L1_Tv_128x47/frame_0.png b/assets/dolphin/external/L1_Tv_128x47/frame_0.png index acc24df00..b37bc412b 100644 Binary files a/assets/dolphin/external/L1_Tv_128x47/frame_0.png and b/assets/dolphin/external/L1_Tv_128x47/frame_0.png differ diff --git a/assets/dolphin/external/L1_Tv_128x47/frame_1.png b/assets/dolphin/external/L1_Tv_128x47/frame_1.png index b0ead7994..848700a7a 100644 Binary files a/assets/dolphin/external/L1_Tv_128x47/frame_1.png and b/assets/dolphin/external/L1_Tv_128x47/frame_1.png differ diff --git a/assets/dolphin/external/L1_Tv_128x47/frame_2.png b/assets/dolphin/external/L1_Tv_128x47/frame_2.png index c1541b2dd..5c74653ec 100644 Binary files a/assets/dolphin/external/L1_Tv_128x47/frame_2.png and b/assets/dolphin/external/L1_Tv_128x47/frame_2.png differ diff --git a/assets/dolphin/external/L1_Tv_128x47/frame_3.png b/assets/dolphin/external/L1_Tv_128x47/frame_3.png index 1e13b0951..5f030e4bb 100644 Binary files a/assets/dolphin/external/L1_Tv_128x47/frame_3.png and b/assets/dolphin/external/L1_Tv_128x47/frame_3.png differ diff --git a/assets/dolphin/external/L1_Tv_128x47/frame_4.png b/assets/dolphin/external/L1_Tv_128x47/frame_4.png index 7d87fa2f8..0b5457d93 100644 Binary files a/assets/dolphin/external/L1_Tv_128x47/frame_4.png and b/assets/dolphin/external/L1_Tv_128x47/frame_4.png differ diff --git a/assets/dolphin/external/L1_Tv_128x47/frame_5.png b/assets/dolphin/external/L1_Tv_128x47/frame_5.png index 282f43059..88c044d34 100644 Binary files a/assets/dolphin/external/L1_Tv_128x47/frame_5.png and b/assets/dolphin/external/L1_Tv_128x47/frame_5.png differ diff --git a/assets/dolphin/external/L1_Tv_128x47/frame_6.png b/assets/dolphin/external/L1_Tv_128x47/frame_6.png index 8516cbe75..ee9c23b39 100644 Binary files a/assets/dolphin/external/L1_Tv_128x47/frame_6.png and b/assets/dolphin/external/L1_Tv_128x47/frame_6.png differ diff --git a/assets/dolphin/external/L1_Tv_128x47/frame_7.png b/assets/dolphin/external/L1_Tv_128x47/frame_7.png index 42196cab1..7074a89f3 100644 Binary files a/assets/dolphin/external/L1_Tv_128x47/frame_7.png and b/assets/dolphin/external/L1_Tv_128x47/frame_7.png differ diff --git a/assets/dolphin/external/L1_Wardriving_128x64/frame_0.png b/assets/dolphin/external/L1_Wardriving_128x64/frame_0.png index db2fc0b46..888a40b0d 100644 Binary files a/assets/dolphin/external/L1_Wardriving_128x64/frame_0.png and b/assets/dolphin/external/L1_Wardriving_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L1_Wardriving_128x64/frame_1.png b/assets/dolphin/external/L1_Wardriving_128x64/frame_1.png index 7b0bfff93..d467d4aef 100644 Binary files a/assets/dolphin/external/L1_Wardriving_128x64/frame_1.png and b/assets/dolphin/external/L1_Wardriving_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L1_Wardriving_128x64/frame_2.png b/assets/dolphin/external/L1_Wardriving_128x64/frame_2.png index 8a33d5543..3dd633bc1 100644 Binary files a/assets/dolphin/external/L1_Wardriving_128x64/frame_2.png and b/assets/dolphin/external/L1_Wardriving_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L1_Wardriving_128x64/frame_3.png b/assets/dolphin/external/L1_Wardriving_128x64/frame_3.png index 6b8162429..dc0883451 100644 Binary files a/assets/dolphin/external/L1_Wardriving_128x64/frame_3.png and b/assets/dolphin/external/L1_Wardriving_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L1_Wardriving_128x64/frame_4.png b/assets/dolphin/external/L1_Wardriving_128x64/frame_4.png index 15678ed07..30792c8f2 100644 Binary files a/assets/dolphin/external/L1_Wardriving_128x64/frame_4.png and b/assets/dolphin/external/L1_Wardriving_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L1_Wardriving_128x64/frame_5.png b/assets/dolphin/external/L1_Wardriving_128x64/frame_5.png index 3b95fb5a4..152b2b53d 100644 Binary files a/assets/dolphin/external/L1_Wardriving_128x64/frame_5.png and b/assets/dolphin/external/L1_Wardriving_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L1_Wardriving_128x64/frame_6.png b/assets/dolphin/external/L1_Wardriving_128x64/frame_6.png index 020921c3a..b79bd23d7 100644 Binary files a/assets/dolphin/external/L1_Wardriving_128x64/frame_6.png and b/assets/dolphin/external/L1_Wardriving_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L1_Wardriving_128x64/frame_7.png b/assets/dolphin/external/L1_Wardriving_128x64/frame_7.png index 6431f9435..1cd7bfdba 100644 Binary files a/assets/dolphin/external/L1_Wardriving_128x64/frame_7.png and b/assets/dolphin/external/L1_Wardriving_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L1_Waves_128x50/frame_0.png b/assets/dolphin/external/L1_Waves_128x50/frame_0.png index adad4f413..aabae9cae 100644 Binary files a/assets/dolphin/external/L1_Waves_128x50/frame_0.png and b/assets/dolphin/external/L1_Waves_128x50/frame_0.png differ diff --git a/assets/dolphin/external/L1_Waves_128x50/frame_1.png b/assets/dolphin/external/L1_Waves_128x50/frame_1.png index 462824be2..4adada4f3 100644 Binary files a/assets/dolphin/external/L1_Waves_128x50/frame_1.png and b/assets/dolphin/external/L1_Waves_128x50/frame_1.png differ diff --git a/assets/dolphin/external/L1_Waves_128x50/frame_2.png b/assets/dolphin/external/L1_Waves_128x50/frame_2.png index a5a728849..84b2453ba 100644 Binary files a/assets/dolphin/external/L1_Waves_128x50/frame_2.png and b/assets/dolphin/external/L1_Waves_128x50/frame_2.png differ diff --git a/assets/dolphin/external/L1_Waves_128x50/frame_3.png b/assets/dolphin/external/L1_Waves_128x50/frame_3.png index 4f454a743..cccfabec1 100644 Binary files a/assets/dolphin/external/L1_Waves_128x50/frame_3.png and b/assets/dolphin/external/L1_Waves_128x50/frame_3.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_0.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_0.png index e34e79690..fc7f15b5e 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_0.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_1.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_1.png index cc6032ad3..bbcc4806f 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_1.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_10.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_10.png index a28a21225..14ba7ef90 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_10.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_10.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_11.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_11.png index 3d94c8910..c2ffa804e 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_11.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_11.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_12.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_12.png index 74e0b962c..ddb78d48c 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_12.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_12.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_13.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_13.png index 3269169e4..dbbb55c39 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_13.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_13.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_14.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_14.png index 42f844d3d..6aa324d8b 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_14.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_14.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_15.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_15.png index 861b16c65..10687b835 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_15.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_15.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_16.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_16.png index 2f4b3b839..862ea4f1e 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_16.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_16.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_17.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_17.png index 7cba6f795..bd08e6dc6 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_17.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_17.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_18.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_18.png index 0b8fe650e..12a96fcf2 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_18.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_18.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_19.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_19.png index e3c50e308..f9fd3f943 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_19.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_19.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_2.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_2.png index c259b5a5a..5f9de6320 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_2.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_20.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_20.png index ae6e76532..96a1c159b 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_20.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_20.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_21.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_21.png index e97affd7e..894c0119c 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_21.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_21.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_22.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_22.png index b5c615924..fcb5f4430 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_22.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_22.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_23.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_23.png index ef4876275..8e8638b82 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_23.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_23.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_24.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_24.png index 4dfe3a029..712cc055e 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_24.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_24.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_25.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_25.png index 1f9d6ac54..9ee574396 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_25.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_25.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_26.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_26.png index 379e29b50..2c3fe6987 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_26.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_26.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_27.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_27.png index 16210a792..3253a415f 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_27.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_27.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_28.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_28.png index 7685c3bc3..2152f449e 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_28.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_28.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_29.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_29.png index 5f114a479..2286f7936 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_29.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_29.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_3.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_3.png index 3f5c523ac..d85c1eb34 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_3.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_30.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_30.png index 645ffa669..d67714a89 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_30.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_30.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_31.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_31.png index a086ba60c..c2371bc4d 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_31.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_31.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_32.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_32.png index 4fdc011d1..43c995266 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_32.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_32.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_33.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_33.png index f9789d8b8..41ff0cced 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_33.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_33.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_34.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_34.png index e13f825fa..05ae0f146 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_34.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_34.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_35.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_35.png index 05f9639b9..61bd92f5f 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_35.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_35.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_36.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_36.png index a968fd015..6924299da 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_36.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_36.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_37.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_37.png index 8393e3ce8..72e71368d 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_37.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_37.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_38.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_38.png index 5e6c32499..2fe57d02d 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_38.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_38.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_39.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_39.png index 7ca97b4a7..8a7e28ebc 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_39.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_39.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_4.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_4.png index 11253dd62..9b2016bba 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_4.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_40.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_40.png index a1ac9f6f3..b471cf949 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_40.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_40.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_41.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_41.png index c33f03e92..7126105ef 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_41.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_41.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_42.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_42.png index dc51592c7..47c4fa671 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_42.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_42.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_43.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_43.png index ff83fe771..c2f6c3fc1 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_43.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_43.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_44.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_44.png index a5488fcb1..bed1de4d1 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_44.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_44.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_45.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_45.png index 86630e83a..221dc2e2d 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_45.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_45.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_46.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_46.png index a9147ae3c..2265cd758 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_46.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_46.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_47.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_47.png index f5b4529e4..857981445 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_47.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_47.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_48.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_48.png index 1f27241b7..72f255746 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_48.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_48.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_49.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_49.png index f5656a750..9a9bb9b45 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_49.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_49.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_5.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_5.png index 1545c0ee7..32aaadfe1 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_5.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_50.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_50.png index 1ff2a8874..2b05c3aa8 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_50.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_50.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_51.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_51.png index 3608e114f..8eb1fb45b 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_51.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_51.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_52.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_52.png index f109b562b..e9815113f 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_52.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_52.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_53.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_53.png index a91b863c7..2b007688f 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_53.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_53.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_54.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_54.png index 052196298..7d2e70cf1 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_54.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_54.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_55.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_55.png index b8a8c6512..90ec097fb 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_55.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_55.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_56.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_56.png index 44f5bf6d2..28c9aefda 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_56.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_56.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_57.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_57.png index f7c1e8023..c9af24f46 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_57.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_57.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_58.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_58.png index 61efe9f45..974638d26 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_58.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_58.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_59.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_59.png index d0bfc886c..258051f3c 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_59.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_59.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_6.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_6.png index f99662e70..a552182fb 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_6.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_60.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_60.png index 950152b73..ea1b5fa6d 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_60.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_60.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_61.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_61.png index 4e430d5c5..203990411 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_61.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_61.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_7.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_7.png index cf09a7842..bc407b6ff 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_7.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_8.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_8.png index d12fa6aba..4ca76f7f9 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_8.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_8.png differ diff --git a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_9.png b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_9.png index ace68d642..e575b6160 100644 Binary files a/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_9.png and b/assets/dolphin/external/L2_Coding_in_the_shell_128x64/frame_9.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_0.png b/assets/dolphin/external/L2_Dj_128x64/frame_0.png index 95f72f901..53b81c0b7 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_0.png and b/assets/dolphin/external/L2_Dj_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_1.png b/assets/dolphin/external/L2_Dj_128x64/frame_1.png index 32e13541d..16a8cc12e 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_1.png and b/assets/dolphin/external/L2_Dj_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_10.png b/assets/dolphin/external/L2_Dj_128x64/frame_10.png index 3cce11f99..eddf421d8 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_10.png and b/assets/dolphin/external/L2_Dj_128x64/frame_10.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_11.png b/assets/dolphin/external/L2_Dj_128x64/frame_11.png index eca4a1296..a3249a298 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_11.png and b/assets/dolphin/external/L2_Dj_128x64/frame_11.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_12.png b/assets/dolphin/external/L2_Dj_128x64/frame_12.png index 5f92e47fd..11019c7e1 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_12.png and b/assets/dolphin/external/L2_Dj_128x64/frame_12.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_13.png b/assets/dolphin/external/L2_Dj_128x64/frame_13.png index 1b1017ce2..90c66281e 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_13.png and b/assets/dolphin/external/L2_Dj_128x64/frame_13.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_14.png b/assets/dolphin/external/L2_Dj_128x64/frame_14.png index 2cf408c97..4365d99f8 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_14.png and b/assets/dolphin/external/L2_Dj_128x64/frame_14.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_15.png b/assets/dolphin/external/L2_Dj_128x64/frame_15.png index 9b796498c..c1f8a5540 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_15.png and b/assets/dolphin/external/L2_Dj_128x64/frame_15.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_16.png b/assets/dolphin/external/L2_Dj_128x64/frame_16.png index c1545500c..f778164ca 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_16.png and b/assets/dolphin/external/L2_Dj_128x64/frame_16.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_17.png b/assets/dolphin/external/L2_Dj_128x64/frame_17.png index 80863f0b6..ddecd6278 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_17.png and b/assets/dolphin/external/L2_Dj_128x64/frame_17.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_18.png b/assets/dolphin/external/L2_Dj_128x64/frame_18.png index b4527bc83..2e777ca2c 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_18.png and b/assets/dolphin/external/L2_Dj_128x64/frame_18.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_19.png b/assets/dolphin/external/L2_Dj_128x64/frame_19.png index f1531da4e..9ed7e2cdd 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_19.png and b/assets/dolphin/external/L2_Dj_128x64/frame_19.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_2.png b/assets/dolphin/external/L2_Dj_128x64/frame_2.png index 391cfe1e1..896772feb 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_2.png and b/assets/dolphin/external/L2_Dj_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_20.png b/assets/dolphin/external/L2_Dj_128x64/frame_20.png index f63904f29..ca4facfbf 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_20.png and b/assets/dolphin/external/L2_Dj_128x64/frame_20.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_21.png b/assets/dolphin/external/L2_Dj_128x64/frame_21.png index 076448fa9..71d2c0fb6 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_21.png and b/assets/dolphin/external/L2_Dj_128x64/frame_21.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_22.png b/assets/dolphin/external/L2_Dj_128x64/frame_22.png index 8651f12f8..f5fe6855f 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_22.png and b/assets/dolphin/external/L2_Dj_128x64/frame_22.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_23.png b/assets/dolphin/external/L2_Dj_128x64/frame_23.png index d2d8e7e51..f7d7c9928 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_23.png and b/assets/dolphin/external/L2_Dj_128x64/frame_23.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_24.png b/assets/dolphin/external/L2_Dj_128x64/frame_24.png index 6080e7aa3..84d314077 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_24.png and b/assets/dolphin/external/L2_Dj_128x64/frame_24.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_25.png b/assets/dolphin/external/L2_Dj_128x64/frame_25.png index ec483addf..1c03f7239 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_25.png and b/assets/dolphin/external/L2_Dj_128x64/frame_25.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_26.png b/assets/dolphin/external/L2_Dj_128x64/frame_26.png index 90fc3b138..601015748 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_26.png and b/assets/dolphin/external/L2_Dj_128x64/frame_26.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_27.png b/assets/dolphin/external/L2_Dj_128x64/frame_27.png index 39ddf46ab..24493753c 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_27.png and b/assets/dolphin/external/L2_Dj_128x64/frame_27.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_28.png b/assets/dolphin/external/L2_Dj_128x64/frame_28.png index f433c969c..638eb8887 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_28.png and b/assets/dolphin/external/L2_Dj_128x64/frame_28.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_29.png b/assets/dolphin/external/L2_Dj_128x64/frame_29.png index 263ffe15a..caf93d855 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_29.png and b/assets/dolphin/external/L2_Dj_128x64/frame_29.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_3.png b/assets/dolphin/external/L2_Dj_128x64/frame_3.png index 40d1314c9..3b99c633a 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_3.png and b/assets/dolphin/external/L2_Dj_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_30.png b/assets/dolphin/external/L2_Dj_128x64/frame_30.png index 27c297e8d..593df1780 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_30.png and b/assets/dolphin/external/L2_Dj_128x64/frame_30.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_31.png b/assets/dolphin/external/L2_Dj_128x64/frame_31.png index f2aefbfae..1a1439ab4 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_31.png and b/assets/dolphin/external/L2_Dj_128x64/frame_31.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_32.png b/assets/dolphin/external/L2_Dj_128x64/frame_32.png index 852c24233..806f28576 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_32.png and b/assets/dolphin/external/L2_Dj_128x64/frame_32.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_33.png b/assets/dolphin/external/L2_Dj_128x64/frame_33.png index 665ac5eaf..637993db5 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_33.png and b/assets/dolphin/external/L2_Dj_128x64/frame_33.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_34.png b/assets/dolphin/external/L2_Dj_128x64/frame_34.png index 81f133ac5..11788d435 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_34.png and b/assets/dolphin/external/L2_Dj_128x64/frame_34.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_35.png b/assets/dolphin/external/L2_Dj_128x64/frame_35.png index c828207d3..23da46851 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_35.png and b/assets/dolphin/external/L2_Dj_128x64/frame_35.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_36.png b/assets/dolphin/external/L2_Dj_128x64/frame_36.png index fc923b402..39ce84076 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_36.png and b/assets/dolphin/external/L2_Dj_128x64/frame_36.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_4.png b/assets/dolphin/external/L2_Dj_128x64/frame_4.png index d372ff643..7ee22d3ca 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_4.png and b/assets/dolphin/external/L2_Dj_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_5.png b/assets/dolphin/external/L2_Dj_128x64/frame_5.png index 5b52f9517..a14d625d3 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_5.png and b/assets/dolphin/external/L2_Dj_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_6.png b/assets/dolphin/external/L2_Dj_128x64/frame_6.png index 8a1e84a11..2087182d9 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_6.png and b/assets/dolphin/external/L2_Dj_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_7.png b/assets/dolphin/external/L2_Dj_128x64/frame_7.png index 1fddffaa4..e9c199f1e 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_7.png and b/assets/dolphin/external/L2_Dj_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_8.png b/assets/dolphin/external/L2_Dj_128x64/frame_8.png index 14ef1aded..e0946ff7e 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_8.png and b/assets/dolphin/external/L2_Dj_128x64/frame_8.png differ diff --git a/assets/dolphin/external/L2_Dj_128x64/frame_9.png b/assets/dolphin/external/L2_Dj_128x64/frame_9.png index 05de5d5c6..ef7a349c9 100644 Binary files a/assets/dolphin/external/L2_Dj_128x64/frame_9.png and b/assets/dolphin/external/L2_Dj_128x64/frame_9.png differ diff --git a/assets/dolphin/external/L2_Furippa2_128x64/frame_0.png b/assets/dolphin/external/L2_Furippa2_128x64/frame_0.png index 43b26283e..5fc9ab425 100644 Binary files a/assets/dolphin/external/L2_Furippa2_128x64/frame_0.png and b/assets/dolphin/external/L2_Furippa2_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L2_Furippa2_128x64/frame_1.png b/assets/dolphin/external/L2_Furippa2_128x64/frame_1.png index fecba5ad5..91b3df523 100644 Binary files a/assets/dolphin/external/L2_Furippa2_128x64/frame_1.png and b/assets/dolphin/external/L2_Furippa2_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L2_Furippa2_128x64/frame_10.png b/assets/dolphin/external/L2_Furippa2_128x64/frame_10.png index 3c15e7ccf..755fb3e86 100644 Binary files a/assets/dolphin/external/L2_Furippa2_128x64/frame_10.png and b/assets/dolphin/external/L2_Furippa2_128x64/frame_10.png differ diff --git a/assets/dolphin/external/L2_Furippa2_128x64/frame_11.png b/assets/dolphin/external/L2_Furippa2_128x64/frame_11.png index 0f293281f..e513b85ca 100644 Binary files a/assets/dolphin/external/L2_Furippa2_128x64/frame_11.png and b/assets/dolphin/external/L2_Furippa2_128x64/frame_11.png differ diff --git a/assets/dolphin/external/L2_Furippa2_128x64/frame_12.png b/assets/dolphin/external/L2_Furippa2_128x64/frame_12.png index 733962d3a..867f8d09f 100644 Binary files a/assets/dolphin/external/L2_Furippa2_128x64/frame_12.png and b/assets/dolphin/external/L2_Furippa2_128x64/frame_12.png differ diff --git a/assets/dolphin/external/L2_Furippa2_128x64/frame_13.png b/assets/dolphin/external/L2_Furippa2_128x64/frame_13.png index 4b7ed184f..45fd1ec4e 100644 Binary files a/assets/dolphin/external/L2_Furippa2_128x64/frame_13.png and b/assets/dolphin/external/L2_Furippa2_128x64/frame_13.png differ diff --git a/assets/dolphin/external/L2_Furippa2_128x64/frame_14.png b/assets/dolphin/external/L2_Furippa2_128x64/frame_14.png index 1efff0f21..1390e1297 100644 Binary files a/assets/dolphin/external/L2_Furippa2_128x64/frame_14.png and b/assets/dolphin/external/L2_Furippa2_128x64/frame_14.png differ diff --git a/assets/dolphin/external/L2_Furippa2_128x64/frame_15.png b/assets/dolphin/external/L2_Furippa2_128x64/frame_15.png index f2d76409d..2e7a73bce 100644 Binary files a/assets/dolphin/external/L2_Furippa2_128x64/frame_15.png and b/assets/dolphin/external/L2_Furippa2_128x64/frame_15.png differ diff --git a/assets/dolphin/external/L2_Furippa2_128x64/frame_16.png b/assets/dolphin/external/L2_Furippa2_128x64/frame_16.png index 125fb98fa..ff101259e 100644 Binary files a/assets/dolphin/external/L2_Furippa2_128x64/frame_16.png and b/assets/dolphin/external/L2_Furippa2_128x64/frame_16.png differ diff --git a/assets/dolphin/external/L2_Furippa2_128x64/frame_17.png b/assets/dolphin/external/L2_Furippa2_128x64/frame_17.png index 3a4a5f5a1..3c5c37469 100644 Binary files a/assets/dolphin/external/L2_Furippa2_128x64/frame_17.png and b/assets/dolphin/external/L2_Furippa2_128x64/frame_17.png differ diff --git a/assets/dolphin/external/L2_Furippa2_128x64/frame_18.png b/assets/dolphin/external/L2_Furippa2_128x64/frame_18.png index 13dd34859..5d7672c4e 100644 Binary files a/assets/dolphin/external/L2_Furippa2_128x64/frame_18.png and b/assets/dolphin/external/L2_Furippa2_128x64/frame_18.png differ diff --git a/assets/dolphin/external/L2_Furippa2_128x64/frame_2.png b/assets/dolphin/external/L2_Furippa2_128x64/frame_2.png index ef3150fd8..da28883c8 100644 Binary files a/assets/dolphin/external/L2_Furippa2_128x64/frame_2.png and b/assets/dolphin/external/L2_Furippa2_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L2_Furippa2_128x64/frame_3.png b/assets/dolphin/external/L2_Furippa2_128x64/frame_3.png index 537ab523e..a82e00c0d 100644 Binary files a/assets/dolphin/external/L2_Furippa2_128x64/frame_3.png and b/assets/dolphin/external/L2_Furippa2_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L2_Furippa2_128x64/frame_4.png b/assets/dolphin/external/L2_Furippa2_128x64/frame_4.png index 873570126..e96b830e4 100644 Binary files a/assets/dolphin/external/L2_Furippa2_128x64/frame_4.png and b/assets/dolphin/external/L2_Furippa2_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L2_Furippa2_128x64/frame_5.png b/assets/dolphin/external/L2_Furippa2_128x64/frame_5.png index dbbeb1fe1..dbbffaad0 100644 Binary files a/assets/dolphin/external/L2_Furippa2_128x64/frame_5.png and b/assets/dolphin/external/L2_Furippa2_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L2_Furippa2_128x64/frame_6.png b/assets/dolphin/external/L2_Furippa2_128x64/frame_6.png index d18085027..441c88567 100644 Binary files a/assets/dolphin/external/L2_Furippa2_128x64/frame_6.png and b/assets/dolphin/external/L2_Furippa2_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L2_Furippa2_128x64/frame_7.png b/assets/dolphin/external/L2_Furippa2_128x64/frame_7.png index 24f9333fe..5fc9ab425 100644 Binary files a/assets/dolphin/external/L2_Furippa2_128x64/frame_7.png and b/assets/dolphin/external/L2_Furippa2_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L2_Furippa2_128x64/frame_8.png b/assets/dolphin/external/L2_Furippa2_128x64/frame_8.png index 30b97cdf5..14e0905fb 100644 Binary files a/assets/dolphin/external/L2_Furippa2_128x64/frame_8.png and b/assets/dolphin/external/L2_Furippa2_128x64/frame_8.png differ diff --git a/assets/dolphin/external/L2_Furippa2_128x64/frame_9.png b/assets/dolphin/external/L2_Furippa2_128x64/frame_9.png index 7ceead056..c194bfa4b 100644 Binary files a/assets/dolphin/external/L2_Furippa2_128x64/frame_9.png and b/assets/dolphin/external/L2_Furippa2_128x64/frame_9.png differ diff --git a/assets/dolphin/external/L2_Hacking_pc_128x64/frame_0.png b/assets/dolphin/external/L2_Hacking_pc_128x64/frame_0.png index d303aef08..4c91dd60b 100644 Binary files a/assets/dolphin/external/L2_Hacking_pc_128x64/frame_0.png and b/assets/dolphin/external/L2_Hacking_pc_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L2_Hacking_pc_128x64/frame_1.png b/assets/dolphin/external/L2_Hacking_pc_128x64/frame_1.png index 45aeb57b5..88849fc6b 100644 Binary files a/assets/dolphin/external/L2_Hacking_pc_128x64/frame_1.png and b/assets/dolphin/external/L2_Hacking_pc_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L2_Hacking_pc_128x64/frame_2.png b/assets/dolphin/external/L2_Hacking_pc_128x64/frame_2.png index a4508f14b..c2e190203 100644 Binary files a/assets/dolphin/external/L2_Hacking_pc_128x64/frame_2.png and b/assets/dolphin/external/L2_Hacking_pc_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L2_Hacking_pc_128x64/frame_3.png b/assets/dolphin/external/L2_Hacking_pc_128x64/frame_3.png index 350002167..cb5868d3f 100644 Binary files a/assets/dolphin/external/L2_Hacking_pc_128x64/frame_3.png and b/assets/dolphin/external/L2_Hacking_pc_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L2_Hacking_pc_128x64/frame_4.png b/assets/dolphin/external/L2_Hacking_pc_128x64/frame_4.png index 7addbf932..4b1f6a2aa 100644 Binary files a/assets/dolphin/external/L2_Hacking_pc_128x64/frame_4.png and b/assets/dolphin/external/L2_Hacking_pc_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_0.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_0.png index 8f29d5e2c..72cb959f0 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_0.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_1.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_1.png index f0756ff85..4716e5b80 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_1.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_10.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_10.png index 03d95e2af..63a84b876 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_10.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_10.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_11.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_11.png index e4cf6ea8d..355502f27 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_11.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_11.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_12.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_12.png index 6a7fe1bbb..b17aa530f 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_12.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_12.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_13.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_13.png index 38171c273..3614a711a 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_13.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_13.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_14.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_14.png index 3eb9a1f63..1ebccc2d2 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_14.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_14.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_15.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_15.png index 624407488..8fb3240d7 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_15.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_15.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_16.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_16.png index f1306c2eb..b59622a7a 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_16.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_16.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_17.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_17.png index ed8d96bab..0f6ec25dd 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_17.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_17.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_18.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_18.png index e1df3ea49..45fd14e8e 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_18.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_18.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_19.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_19.png index d231a6561..3fdc37116 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_19.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_19.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_2.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_2.png index e2a864c76..392db9fc6 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_2.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_20.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_20.png index ddf9d4931..3b2292c9c 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_20.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_20.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_21.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_21.png index 0d407de64..904d2931f 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_21.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_21.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_22.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_22.png index f53ee0588..4e0235770 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_22.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_22.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_23.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_23.png index 83be68d84..18b103c40 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_23.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_23.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_24.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_24.png index ae61e5831..9cae5887c 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_24.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_24.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_25.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_25.png index a2608a0e1..c44defec7 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_25.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_25.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_26.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_26.png index 6602e3f57..8adee40b9 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_26.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_26.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_27.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_27.png index e82d7fcd1..b2521cee3 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_27.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_27.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_28.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_28.png index b16dda91d..5a5043ec5 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_28.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_28.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_29.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_29.png index cf91009bf..04bb206bc 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_29.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_29.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_3.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_3.png index 8bfdcabda..0c559c37d 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_3.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_30.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_30.png index 080748498..44eec1f24 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_30.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_30.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_31.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_31.png index d4dfbce33..fa18ea345 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_31.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_31.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_32.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_32.png index c9c169f2e..13bc7f178 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_32.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_32.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_33.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_33.png index 0e939aa2d..6cb3f7c8b 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_33.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_33.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_34.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_34.png index d0f3a5383..0b0d3e5b5 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_34.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_34.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_35.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_35.png index 2e3a3c64f..ab2515fec 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_35.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_35.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_36.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_36.png index 4b34fe377..5dcd576da 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_36.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_36.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_37.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_37.png index 4935b75a6..a28bd7bd9 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_37.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_37.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_38.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_38.png index ccf5bdf09..816227efa 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_38.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_38.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_39.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_39.png index d276c2123..dba19aeeb 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_39.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_39.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_4.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_4.png index 354a96b6c..84acd2bda 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_4.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_40.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_40.png index 873386a57..de8a4e7de 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_40.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_40.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_41.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_41.png index 529f6cdd4..f614ecd7d 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_41.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_41.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_42.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_42.png index 15168cd11..97e67dba0 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_42.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_42.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_43.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_43.png index 16196a706..bc9c6dc21 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_43.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_43.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_44.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_44.png index 06fb27905..8e271e10a 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_44.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_44.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_45.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_45.png index 5a2221cb9..026064c5a 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_45.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_45.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_46.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_46.png index 7db77e935..11f50e232 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_46.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_46.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_47.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_47.png index a6d5407ad..4dbb14ce9 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_47.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_47.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_48.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_48.png index c6a17fda8..a6efbbdcf 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_48.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_48.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_49.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_49.png index 0e6845ac2..58993db8b 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_49.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_49.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_5.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_5.png index 45decf285..8654008fd 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_5.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_50.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_50.png index aa121a538..bcebe86cd 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_50.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_50.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_51.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_51.png index 38184aa75..4d732c392 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_51.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_51.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_52.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_52.png index 1259a591a..b2a87c442 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_52.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_52.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_6.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_6.png index cd916c404..dea4a6c8f 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_6.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_7.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_7.png index d28bb5454..da9f67db4 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_7.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_8.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_8.png index 3621243f7..567ac58ac 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_8.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_8.png differ diff --git a/assets/dolphin/external/L2_Secret_door_128x64/frame_9.png b/assets/dolphin/external/L2_Secret_door_128x64/frame_9.png index 4d3d53716..cc05c1603 100644 Binary files a/assets/dolphin/external/L2_Secret_door_128x64/frame_9.png and b/assets/dolphin/external/L2_Secret_door_128x64/frame_9.png differ diff --git a/assets/dolphin/external/L2_Soldering_128x64/frame_0.png b/assets/dolphin/external/L2_Soldering_128x64/frame_0.png index bd20ae843..db6877259 100644 Binary files a/assets/dolphin/external/L2_Soldering_128x64/frame_0.png and b/assets/dolphin/external/L2_Soldering_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L2_Soldering_128x64/frame_1.png b/assets/dolphin/external/L2_Soldering_128x64/frame_1.png index b9453d056..0ff99dc58 100644 Binary files a/assets/dolphin/external/L2_Soldering_128x64/frame_1.png and b/assets/dolphin/external/L2_Soldering_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L2_Soldering_128x64/frame_10.png b/assets/dolphin/external/L2_Soldering_128x64/frame_10.png index 0519e851d..b9c3a2797 100644 Binary files a/assets/dolphin/external/L2_Soldering_128x64/frame_10.png and b/assets/dolphin/external/L2_Soldering_128x64/frame_10.png differ diff --git a/assets/dolphin/external/L2_Soldering_128x64/frame_2.png b/assets/dolphin/external/L2_Soldering_128x64/frame_2.png index 514241266..c0adab346 100644 Binary files a/assets/dolphin/external/L2_Soldering_128x64/frame_2.png and b/assets/dolphin/external/L2_Soldering_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L2_Soldering_128x64/frame_3.png b/assets/dolphin/external/L2_Soldering_128x64/frame_3.png index ba7ad99ae..27808c97b 100644 Binary files a/assets/dolphin/external/L2_Soldering_128x64/frame_3.png and b/assets/dolphin/external/L2_Soldering_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L2_Soldering_128x64/frame_4.png b/assets/dolphin/external/L2_Soldering_128x64/frame_4.png index ca696e4cf..324938865 100644 Binary files a/assets/dolphin/external/L2_Soldering_128x64/frame_4.png and b/assets/dolphin/external/L2_Soldering_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L2_Soldering_128x64/frame_5.png b/assets/dolphin/external/L2_Soldering_128x64/frame_5.png index aa7fc8ea0..43cb2a283 100644 Binary files a/assets/dolphin/external/L2_Soldering_128x64/frame_5.png and b/assets/dolphin/external/L2_Soldering_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L2_Soldering_128x64/frame_6.png b/assets/dolphin/external/L2_Soldering_128x64/frame_6.png index 85d1e30c9..29d09c423 100644 Binary files a/assets/dolphin/external/L2_Soldering_128x64/frame_6.png and b/assets/dolphin/external/L2_Soldering_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L2_Soldering_128x64/frame_7.png b/assets/dolphin/external/L2_Soldering_128x64/frame_7.png index 5ef6820f9..b2730636c 100644 Binary files a/assets/dolphin/external/L2_Soldering_128x64/frame_7.png and b/assets/dolphin/external/L2_Soldering_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L2_Soldering_128x64/frame_8.png b/assets/dolphin/external/L2_Soldering_128x64/frame_8.png index 12bed1b4a..f74c6415d 100644 Binary files a/assets/dolphin/external/L2_Soldering_128x64/frame_8.png and b/assets/dolphin/external/L2_Soldering_128x64/frame_8.png differ diff --git a/assets/dolphin/external/L2_Soldering_128x64/frame_9.png b/assets/dolphin/external/L2_Soldering_128x64/frame_9.png index 46f9fd378..3f4d80b04 100644 Binary files a/assets/dolphin/external/L2_Soldering_128x64/frame_9.png and b/assets/dolphin/external/L2_Soldering_128x64/frame_9.png differ diff --git a/assets/dolphin/external/L2_Wake_up_128x64/frame_0.png b/assets/dolphin/external/L2_Wake_up_128x64/frame_0.png index 912090032..f85f1df6b 100644 Binary files a/assets/dolphin/external/L2_Wake_up_128x64/frame_0.png and b/assets/dolphin/external/L2_Wake_up_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L2_Wake_up_128x64/frame_1.png b/assets/dolphin/external/L2_Wake_up_128x64/frame_1.png index 0b99a32ff..6b614c773 100644 Binary files a/assets/dolphin/external/L2_Wake_up_128x64/frame_1.png and b/assets/dolphin/external/L2_Wake_up_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L2_Wake_up_128x64/frame_10.png b/assets/dolphin/external/L2_Wake_up_128x64/frame_10.png index 9da72ac1d..3e7749145 100644 Binary files a/assets/dolphin/external/L2_Wake_up_128x64/frame_10.png and b/assets/dolphin/external/L2_Wake_up_128x64/frame_10.png differ diff --git a/assets/dolphin/external/L2_Wake_up_128x64/frame_11.png b/assets/dolphin/external/L2_Wake_up_128x64/frame_11.png index 8d54da6c6..a90b2f6c0 100644 Binary files a/assets/dolphin/external/L2_Wake_up_128x64/frame_11.png and b/assets/dolphin/external/L2_Wake_up_128x64/frame_11.png differ diff --git a/assets/dolphin/external/L2_Wake_up_128x64/frame_12.png b/assets/dolphin/external/L2_Wake_up_128x64/frame_12.png index 84046a46c..69605e7a2 100644 Binary files a/assets/dolphin/external/L2_Wake_up_128x64/frame_12.png and b/assets/dolphin/external/L2_Wake_up_128x64/frame_12.png differ diff --git a/assets/dolphin/external/L2_Wake_up_128x64/frame_13.png b/assets/dolphin/external/L2_Wake_up_128x64/frame_13.png index 3e1c9c329..cadad766a 100644 Binary files a/assets/dolphin/external/L2_Wake_up_128x64/frame_13.png and b/assets/dolphin/external/L2_Wake_up_128x64/frame_13.png differ diff --git a/assets/dolphin/external/L2_Wake_up_128x64/frame_14.png b/assets/dolphin/external/L2_Wake_up_128x64/frame_14.png index f4f6ccd66..741e4b58f 100644 Binary files a/assets/dolphin/external/L2_Wake_up_128x64/frame_14.png and b/assets/dolphin/external/L2_Wake_up_128x64/frame_14.png differ diff --git a/assets/dolphin/external/L2_Wake_up_128x64/frame_15.png b/assets/dolphin/external/L2_Wake_up_128x64/frame_15.png index 5dc1a6525..855be515d 100644 Binary files a/assets/dolphin/external/L2_Wake_up_128x64/frame_15.png and b/assets/dolphin/external/L2_Wake_up_128x64/frame_15.png differ diff --git a/assets/dolphin/external/L2_Wake_up_128x64/frame_16.png b/assets/dolphin/external/L2_Wake_up_128x64/frame_16.png index bec472921..580e5ef38 100644 Binary files a/assets/dolphin/external/L2_Wake_up_128x64/frame_16.png and b/assets/dolphin/external/L2_Wake_up_128x64/frame_16.png differ diff --git a/assets/dolphin/external/L2_Wake_up_128x64/frame_17.png b/assets/dolphin/external/L2_Wake_up_128x64/frame_17.png index 82e5176c8..59efda005 100644 Binary files a/assets/dolphin/external/L2_Wake_up_128x64/frame_17.png and b/assets/dolphin/external/L2_Wake_up_128x64/frame_17.png differ diff --git a/assets/dolphin/external/L2_Wake_up_128x64/frame_18.png b/assets/dolphin/external/L2_Wake_up_128x64/frame_18.png index 3b5e60dfd..7982ae714 100644 Binary files a/assets/dolphin/external/L2_Wake_up_128x64/frame_18.png and b/assets/dolphin/external/L2_Wake_up_128x64/frame_18.png differ diff --git a/assets/dolphin/external/L2_Wake_up_128x64/frame_19.png b/assets/dolphin/external/L2_Wake_up_128x64/frame_19.png index 5f76c7d23..4017dc1d5 100644 Binary files a/assets/dolphin/external/L2_Wake_up_128x64/frame_19.png and b/assets/dolphin/external/L2_Wake_up_128x64/frame_19.png differ diff --git a/assets/dolphin/external/L2_Wake_up_128x64/frame_2.png b/assets/dolphin/external/L2_Wake_up_128x64/frame_2.png index 84d6aaf35..ffc82fd6f 100644 Binary files a/assets/dolphin/external/L2_Wake_up_128x64/frame_2.png and b/assets/dolphin/external/L2_Wake_up_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L2_Wake_up_128x64/frame_20.png b/assets/dolphin/external/L2_Wake_up_128x64/frame_20.png index 2f8394fd5..99dbc3e08 100644 Binary files a/assets/dolphin/external/L2_Wake_up_128x64/frame_20.png and b/assets/dolphin/external/L2_Wake_up_128x64/frame_20.png differ diff --git a/assets/dolphin/external/L2_Wake_up_128x64/frame_3.png b/assets/dolphin/external/L2_Wake_up_128x64/frame_3.png index 48adde113..f13628011 100644 Binary files a/assets/dolphin/external/L2_Wake_up_128x64/frame_3.png and b/assets/dolphin/external/L2_Wake_up_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L2_Wake_up_128x64/frame_4.png b/assets/dolphin/external/L2_Wake_up_128x64/frame_4.png index 5889835b7..5a0c613c9 100644 Binary files a/assets/dolphin/external/L2_Wake_up_128x64/frame_4.png and b/assets/dolphin/external/L2_Wake_up_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L2_Wake_up_128x64/frame_5.png b/assets/dolphin/external/L2_Wake_up_128x64/frame_5.png index 7f980f57f..61e2d1981 100644 Binary files a/assets/dolphin/external/L2_Wake_up_128x64/frame_5.png and b/assets/dolphin/external/L2_Wake_up_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L2_Wake_up_128x64/frame_6.png b/assets/dolphin/external/L2_Wake_up_128x64/frame_6.png index 497136000..1c6402cec 100644 Binary files a/assets/dolphin/external/L2_Wake_up_128x64/frame_6.png and b/assets/dolphin/external/L2_Wake_up_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L2_Wake_up_128x64/frame_7.png b/assets/dolphin/external/L2_Wake_up_128x64/frame_7.png index 03d67134a..37ea651ab 100644 Binary files a/assets/dolphin/external/L2_Wake_up_128x64/frame_7.png and b/assets/dolphin/external/L2_Wake_up_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L2_Wake_up_128x64/frame_8.png b/assets/dolphin/external/L2_Wake_up_128x64/frame_8.png index 9f523cace..5fdf6365d 100644 Binary files a/assets/dolphin/external/L2_Wake_up_128x64/frame_8.png and b/assets/dolphin/external/L2_Wake_up_128x64/frame_8.png differ diff --git a/assets/dolphin/external/L2_Wake_up_128x64/frame_9.png b/assets/dolphin/external/L2_Wake_up_128x64/frame_9.png index 5a565b1af..9979896e4 100644 Binary files a/assets/dolphin/external/L2_Wake_up_128x64/frame_9.png and b/assets/dolphin/external/L2_Wake_up_128x64/frame_9.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_0.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_0.png index 7d42cb57d..1c854de70 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_0.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_1.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_1.png index 25b4609c3..38e775d81 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_1.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_10.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_10.png index 575df3b9f..4aa332198 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_10.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_10.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_11.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_11.png index 2cfc582ef..4145c3efa 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_11.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_11.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_12.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_12.png index 4aa135cd6..214455e57 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_12.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_12.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_13.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_13.png index aae2827e8..d69939385 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_13.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_13.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_14.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_14.png index a66867a32..cf333a85e 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_14.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_14.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_15.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_15.png index 7ec1216e3..173de44e8 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_15.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_15.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_16.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_16.png index 2632103d6..be5e5fc3f 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_16.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_16.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_17.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_17.png index f50cd0b88..9857478f8 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_17.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_17.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_18.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_18.png index b5a85de1d..3f6ed88b1 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_18.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_18.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_19.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_19.png index d9a29def6..c02f58c52 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_19.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_19.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_2.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_2.png index ca4bf322b..61880587f 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_2.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_20.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_20.png index fe95a716c..e9fd6041f 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_20.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_20.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_21.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_21.png index 6a40d4148..db36ad5fa 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_21.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_21.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_22.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_22.png index 67189811d..72a78cde2 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_22.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_22.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_23.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_23.png index b770f3208..2a042e23e 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_23.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_23.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_24.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_24.png index 4a899faf2..f26aece8c 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_24.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_24.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_25.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_25.png index c12a583f5..e7bec7eed 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_25.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_25.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_26.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_26.png index f62f6495e..85b4e2ee9 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_26.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_26.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_27.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_27.png index 37218c396..ea3a6adf8 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_27.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_27.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_28.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_28.png index a28511c91..96328c9b2 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_28.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_28.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_29.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_29.png index f18f8798d..9334a3e83 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_29.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_29.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_3.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_3.png index 93e694375..1705c1f90 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_3.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_30.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_30.png index 64cf58580..67d6c1234 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_30.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_30.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_31.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_31.png index 2502b3f21..9cf2edd6f 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_31.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_31.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_32.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_32.png index 417419f85..1737a82cf 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_32.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_32.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_33.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_33.png index 5c7906075..a7a0ed870 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_33.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_33.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_34.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_34.png index 26dfe5391..3ef1e8f61 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_34.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_34.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_35.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_35.png index b6d507057..4f009f28c 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_35.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_35.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_36.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_36.png index 7bd425e1d..414041750 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_36.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_36.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_37.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_37.png index 7edea62a1..5432c2e0d 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_37.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_37.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_38.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_38.png index 7b51b6a34..2ad368010 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_38.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_38.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_39.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_39.png index 30b6bd67e..6f8b4f0ca 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_39.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_39.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_4.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_4.png index ff0b1fb28..8ee956c4b 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_4.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_40.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_40.png index d413cf0ed..24de01dab 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_40.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_40.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_41.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_41.png index 277077265..beac49ed8 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_41.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_41.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_42.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_42.png index baf3c7c79..2a095979a 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_42.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_42.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_43.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_43.png index b4cb1179f..32e35f4ba 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_43.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_43.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_44.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_44.png index 09dfc28e8..74552749e 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_44.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_44.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_45.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_45.png index 94b26fe06..de4d7cacc 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_45.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_45.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_46.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_46.png index 28f47d714..bb5719795 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_46.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_46.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_47.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_47.png index a9cc34ca2..8aaceac98 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_47.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_47.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_48.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_48.png index cc9a89dad..11e017674 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_48.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_48.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_49.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_49.png index ef68cf866..c667c9f81 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_49.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_49.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_5.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_5.png index b0367a603..8becdf394 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_5.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_50.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_50.png index a44a566c7..d3305472c 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_50.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_50.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_51.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_51.png index ba00473dd..3d7005fb6 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_51.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_51.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_52.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_52.png index 8045749ac..a7db03a33 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_52.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_52.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_53.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_53.png index 18337cd63..f443ae5c3 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_53.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_53.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_54.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_54.png index 10be0ad16..a32249641 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_54.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_54.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_55.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_55.png index fd8269bb4..da7a84aea 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_55.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_55.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_56.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_56.png index 300cbd9ec..7d0b0732a 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_56.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_56.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_6.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_6.png index 56f37fbd8..bdbff35e6 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_6.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_7.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_7.png index 0e4fb27a6..4be5ea9ac 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_7.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_8.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_8.png index 641d06f39..3cd04384e 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_8.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_8.png differ diff --git a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_9.png b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_9.png index 5bcf7e588..a711a3794 100755 Binary files a/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_9.png and b/assets/dolphin/external/L3_Freedom_2_dolphins_128x64/frame_9.png differ diff --git a/assets/dolphin/external/L3_Furippa3_128x64/frame_0.png b/assets/dolphin/external/L3_Furippa3_128x64/frame_0.png index 3b82285e6..5d61be5a2 100644 Binary files a/assets/dolphin/external/L3_Furippa3_128x64/frame_0.png and b/assets/dolphin/external/L3_Furippa3_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L3_Furippa3_128x64/frame_1.png b/assets/dolphin/external/L3_Furippa3_128x64/frame_1.png index 7af08829b..e649beb88 100644 Binary files a/assets/dolphin/external/L3_Furippa3_128x64/frame_1.png and b/assets/dolphin/external/L3_Furippa3_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L3_Furippa3_128x64/frame_10.png b/assets/dolphin/external/L3_Furippa3_128x64/frame_10.png index 0ef6d471d..ce8a2e0ea 100644 Binary files a/assets/dolphin/external/L3_Furippa3_128x64/frame_10.png and b/assets/dolphin/external/L3_Furippa3_128x64/frame_10.png differ diff --git a/assets/dolphin/external/L3_Furippa3_128x64/frame_11.png b/assets/dolphin/external/L3_Furippa3_128x64/frame_11.png index e6f397eb8..c49d6463d 100644 Binary files a/assets/dolphin/external/L3_Furippa3_128x64/frame_11.png and b/assets/dolphin/external/L3_Furippa3_128x64/frame_11.png differ diff --git a/assets/dolphin/external/L3_Furippa3_128x64/frame_12.png b/assets/dolphin/external/L3_Furippa3_128x64/frame_12.png index 9221fb156..867f8d09f 100644 Binary files a/assets/dolphin/external/L3_Furippa3_128x64/frame_12.png and b/assets/dolphin/external/L3_Furippa3_128x64/frame_12.png differ diff --git a/assets/dolphin/external/L3_Furippa3_128x64/frame_13.png b/assets/dolphin/external/L3_Furippa3_128x64/frame_13.png index e43b1edb8..45fd1ec4e 100644 Binary files a/assets/dolphin/external/L3_Furippa3_128x64/frame_13.png and b/assets/dolphin/external/L3_Furippa3_128x64/frame_13.png differ diff --git a/assets/dolphin/external/L3_Furippa3_128x64/frame_14.png b/assets/dolphin/external/L3_Furippa3_128x64/frame_14.png index 64da8d8f9..1390e1297 100644 Binary files a/assets/dolphin/external/L3_Furippa3_128x64/frame_14.png and b/assets/dolphin/external/L3_Furippa3_128x64/frame_14.png differ diff --git a/assets/dolphin/external/L3_Furippa3_128x64/frame_15.png b/assets/dolphin/external/L3_Furippa3_128x64/frame_15.png index 96b196696..228c29482 100644 Binary files a/assets/dolphin/external/L3_Furippa3_128x64/frame_15.png and b/assets/dolphin/external/L3_Furippa3_128x64/frame_15.png differ diff --git a/assets/dolphin/external/L3_Furippa3_128x64/frame_16.png b/assets/dolphin/external/L3_Furippa3_128x64/frame_16.png index 620dbca29..85bd8bbd9 100644 Binary files a/assets/dolphin/external/L3_Furippa3_128x64/frame_16.png and b/assets/dolphin/external/L3_Furippa3_128x64/frame_16.png differ diff --git a/assets/dolphin/external/L3_Furippa3_128x64/frame_17.png b/assets/dolphin/external/L3_Furippa3_128x64/frame_17.png index 49aa979d7..69e9260df 100644 Binary files a/assets/dolphin/external/L3_Furippa3_128x64/frame_17.png and b/assets/dolphin/external/L3_Furippa3_128x64/frame_17.png differ diff --git a/assets/dolphin/external/L3_Furippa3_128x64/frame_18.png b/assets/dolphin/external/L3_Furippa3_128x64/frame_18.png index 7739e294a..21d2a4c2c 100644 Binary files a/assets/dolphin/external/L3_Furippa3_128x64/frame_18.png and b/assets/dolphin/external/L3_Furippa3_128x64/frame_18.png differ diff --git a/assets/dolphin/external/L3_Furippa3_128x64/frame_2.png b/assets/dolphin/external/L3_Furippa3_128x64/frame_2.png index c36e54b2f..bfc521d16 100644 Binary files a/assets/dolphin/external/L3_Furippa3_128x64/frame_2.png and b/assets/dolphin/external/L3_Furippa3_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L3_Furippa3_128x64/frame_3.png b/assets/dolphin/external/L3_Furippa3_128x64/frame_3.png index dce96b74c..a67a1a2fe 100644 Binary files a/assets/dolphin/external/L3_Furippa3_128x64/frame_3.png and b/assets/dolphin/external/L3_Furippa3_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L3_Furippa3_128x64/frame_4.png b/assets/dolphin/external/L3_Furippa3_128x64/frame_4.png index 2c096689a..f4e9cf284 100644 Binary files a/assets/dolphin/external/L3_Furippa3_128x64/frame_4.png and b/assets/dolphin/external/L3_Furippa3_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L3_Furippa3_128x64/frame_5.png b/assets/dolphin/external/L3_Furippa3_128x64/frame_5.png index 792719974..f7965d9f7 100644 Binary files a/assets/dolphin/external/L3_Furippa3_128x64/frame_5.png and b/assets/dolphin/external/L3_Furippa3_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L3_Furippa3_128x64/frame_6.png b/assets/dolphin/external/L3_Furippa3_128x64/frame_6.png index 689e7dd79..3288f6ab9 100644 Binary files a/assets/dolphin/external/L3_Furippa3_128x64/frame_6.png and b/assets/dolphin/external/L3_Furippa3_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L3_Furippa3_128x64/frame_7.png b/assets/dolphin/external/L3_Furippa3_128x64/frame_7.png index 7b468ab83..5d61be5a2 100644 Binary files a/assets/dolphin/external/L3_Furippa3_128x64/frame_7.png and b/assets/dolphin/external/L3_Furippa3_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L3_Furippa3_128x64/frame_8.png b/assets/dolphin/external/L3_Furippa3_128x64/frame_8.png index e9246c0b7..a3484079c 100644 Binary files a/assets/dolphin/external/L3_Furippa3_128x64/frame_8.png and b/assets/dolphin/external/L3_Furippa3_128x64/frame_8.png differ diff --git a/assets/dolphin/external/L3_Furippa3_128x64/frame_9.png b/assets/dolphin/external/L3_Furippa3_128x64/frame_9.png index c2e164c51..08b590cfa 100644 Binary files a/assets/dolphin/external/L3_Furippa3_128x64/frame_9.png and b/assets/dolphin/external/L3_Furippa3_128x64/frame_9.png differ diff --git a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_0.png b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_0.png index 6fb7de66c..e27622b52 100644 Binary files a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_0.png and b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_1.png b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_1.png index eaf39cff4..ccff2357c 100644 Binary files a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_1.png and b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_10.png b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_10.png index 1e3890a7b..b3c3c9d2d 100644 Binary files a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_10.png and b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_10.png differ diff --git a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_11.png b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_11.png index fc8aef13a..c190e3f26 100644 Binary files a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_11.png and b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_11.png differ diff --git a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_12.png b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_12.png index 8174af0d1..23616dd11 100644 Binary files a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_12.png and b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_12.png differ diff --git a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_13.png b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_13.png index b5e75921a..6c721fb56 100644 Binary files a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_13.png and b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_13.png differ diff --git a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_2.png b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_2.png index 6a239a1b6..a5b657e10 100644 Binary files a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_2.png and b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_3.png b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_3.png index 8cec74395..525fb1a50 100644 Binary files a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_3.png and b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_4.png b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_4.png index d034b0a53..5708bef7d 100644 Binary files a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_4.png and b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_5.png b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_5.png index 472241e56..7df699013 100644 Binary files a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_5.png and b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_6.png b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_6.png index db53a0bb4..7b138689c 100644 Binary files a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_6.png and b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_7.png b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_7.png index f2015a77d..4049043fa 100644 Binary files a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_7.png and b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_8.png b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_8.png index 39b8d5f8f..8b8cf564f 100644 Binary files a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_8.png and b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_8.png differ diff --git a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_9.png b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_9.png index 8b5e6f5ee..5824e3144 100644 Binary files a/assets/dolphin/external/L3_Hijack_radio_128x64/frame_9.png and b/assets/dolphin/external/L3_Hijack_radio_128x64/frame_9.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_0.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_0.png index b937cc086..3b179a0d4 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_0.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_1.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_1.png index a3b494dda..bba17279d 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_1.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_10.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_10.png index b8163164b..5016136e5 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_10.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_10.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_11.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_11.png index e685ff86a..95c1a8a32 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_11.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_11.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_12.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_12.png index 10a52400b..fd0a6c625 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_12.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_12.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_13.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_13.png index 9cdea5002..4f4a2623c 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_13.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_13.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_14.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_14.png index 590d0bf89..cfdaf02e8 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_14.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_14.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_15.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_15.png index 97cf05dd0..e046d9415 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_15.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_15.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_16.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_16.png index e2bae209f..812de0b35 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_16.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_16.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_17.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_17.png index 63db9fa0e..cfd6410d6 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_17.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_17.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_18.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_18.png index ad66f34ef..255818b91 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_18.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_18.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_19.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_19.png index 213fb7636..38588da72 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_19.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_19.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_2.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_2.png index 81174f7fa..d0426c0fc 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_2.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_20.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_20.png index 7f4ce3bac..38083a472 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_20.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_20.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_21.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_21.png index dc90311fe..051b0d867 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_21.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_21.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_22.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_22.png index cda17cb60..af08ce0f6 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_22.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_22.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_23.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_23.png index 7a048dbae..1ef1f5746 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_23.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_23.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_24.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_24.png index c5a80a925..b18f8ea68 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_24.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_24.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_25.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_25.png index e80fdfb00..13657d515 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_25.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_25.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_26.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_26.png index b3955ac8a..d93dc9aa7 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_26.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_26.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_27.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_27.png index 4b003d034..c7f848cb7 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_27.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_27.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_28.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_28.png index df2008d93..adcae64da 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_28.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_28.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_29.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_29.png index c0afacdfa..05dd84317 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_29.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_29.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_3.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_3.png index 97c138235..d8155c7e2 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_3.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_30.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_30.png index 6f693de4f..9b60bc189 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_30.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_30.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_31.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_31.png index c971b2178..19ae6d56f 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_31.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_31.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_32.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_32.png index 856c84557..dcc5cfdde 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_32.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_32.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_33.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_33.png index 7e99a4a82..f47fa0a14 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_33.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_33.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_34.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_34.png index 949d845d4..723a18bee 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_34.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_34.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_35.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_35.png index ee7be1409..d65d6354b 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_35.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_35.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_36.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_36.png index ae6fca1cd..880b9df52 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_36.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_36.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_37.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_37.png index 2567cf087..5c890d433 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_37.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_37.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_38.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_38.png index b3d0c7acf..6767d5b91 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_38.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_38.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_39.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_39.png index dd98cfcbd..2e2a98e5c 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_39.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_39.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_4.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_4.png index 0f81cd5dc..bf55efc7d 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_4.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_40.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_40.png index 8e55dd9ed..4b13e0a0b 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_40.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_40.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_41.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_41.png index 459f0c8e6..ce0952aaf 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_41.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_41.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_42.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_42.png index 3c0955993..19de275d9 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_42.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_42.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_43.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_43.png index 32d4eb4f1..95e61d24f 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_43.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_43.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_44.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_44.png index 11bd640ae..f9085a27d 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_44.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_44.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_45.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_45.png index 27af626e8..aa319ee4e 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_45.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_45.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_46.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_46.png index cfc81bd3f..2c9fddb14 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_46.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_46.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_47.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_47.png index f9480b1e3..26f023fdc 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_47.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_47.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_48.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_48.png index 6793a3df6..7c5bb3ecd 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_48.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_48.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_49.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_49.png index 6b58a0fa7..4e40165cd 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_49.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_49.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_5.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_5.png index cb62bb7b3..7c0c0539d 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_5.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_50.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_50.png index 8b5ab6a9b..0fc0f27b6 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_50.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_50.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_51.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_51.png index 9a2c6b150..c8f1b6c45 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_51.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_51.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_52.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_52.png index f7da1b587..043481281 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_52.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_52.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_53.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_53.png index d8e390bb5..cb8d0f15f 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_53.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_53.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_54.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_54.png index 8dfe5defe..66179fcd1 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_54.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_54.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_55.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_55.png index fae299733..0c25fab74 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_55.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_55.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_6.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_6.png index 2d111a7a1..15034fad3 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_6.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_7.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_7.png index 4c8a9d2e5..d5d30c8ed 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_7.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_8.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_8.png index aa0d1e6a7..dab8497c8 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_8.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_8.png differ diff --git a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_9.png b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_9.png index 9f2d03b7e..e445ae752 100755 Binary files a/assets/dolphin/external/L3_Intruder_alert_128x64/frame_9.png and b/assets/dolphin/external/L3_Intruder_alert_128x64/frame_9.png differ diff --git a/assets/dolphin/external/L3_Lab_research_128x54/frame_0.png b/assets/dolphin/external/L3_Lab_research_128x54/frame_0.png index c85bb77c4..3d170012c 100644 Binary files a/assets/dolphin/external/L3_Lab_research_128x54/frame_0.png and b/assets/dolphin/external/L3_Lab_research_128x54/frame_0.png differ diff --git a/assets/dolphin/external/L3_Lab_research_128x54/frame_1.png b/assets/dolphin/external/L3_Lab_research_128x54/frame_1.png index dedff6024..2c4b10234 100644 Binary files a/assets/dolphin/external/L3_Lab_research_128x54/frame_1.png and b/assets/dolphin/external/L3_Lab_research_128x54/frame_1.png differ diff --git a/assets/dolphin/external/L3_Lab_research_128x54/frame_10.png b/assets/dolphin/external/L3_Lab_research_128x54/frame_10.png index 1a53ab75d..1fed4fbe9 100644 Binary files a/assets/dolphin/external/L3_Lab_research_128x54/frame_10.png and b/assets/dolphin/external/L3_Lab_research_128x54/frame_10.png differ diff --git a/assets/dolphin/external/L3_Lab_research_128x54/frame_11.png b/assets/dolphin/external/L3_Lab_research_128x54/frame_11.png index 1768d50dd..749ea4966 100644 Binary files a/assets/dolphin/external/L3_Lab_research_128x54/frame_11.png and b/assets/dolphin/external/L3_Lab_research_128x54/frame_11.png differ diff --git a/assets/dolphin/external/L3_Lab_research_128x54/frame_12.png b/assets/dolphin/external/L3_Lab_research_128x54/frame_12.png index 2beb237d9..489c53035 100644 Binary files a/assets/dolphin/external/L3_Lab_research_128x54/frame_12.png and b/assets/dolphin/external/L3_Lab_research_128x54/frame_12.png differ diff --git a/assets/dolphin/external/L3_Lab_research_128x54/frame_13.png b/assets/dolphin/external/L3_Lab_research_128x54/frame_13.png index c46dc3bab..daa7667cc 100644 Binary files a/assets/dolphin/external/L3_Lab_research_128x54/frame_13.png and b/assets/dolphin/external/L3_Lab_research_128x54/frame_13.png differ diff --git a/assets/dolphin/external/L3_Lab_research_128x54/frame_2.png b/assets/dolphin/external/L3_Lab_research_128x54/frame_2.png index 01f07c68d..34650daa6 100644 Binary files a/assets/dolphin/external/L3_Lab_research_128x54/frame_2.png and b/assets/dolphin/external/L3_Lab_research_128x54/frame_2.png differ diff --git a/assets/dolphin/external/L3_Lab_research_128x54/frame_3.png b/assets/dolphin/external/L3_Lab_research_128x54/frame_3.png index 148fe4640..7da00632d 100644 Binary files a/assets/dolphin/external/L3_Lab_research_128x54/frame_3.png and b/assets/dolphin/external/L3_Lab_research_128x54/frame_3.png differ diff --git a/assets/dolphin/external/L3_Lab_research_128x54/frame_4.png b/assets/dolphin/external/L3_Lab_research_128x54/frame_4.png index 0d402b0db..e9de77eea 100644 Binary files a/assets/dolphin/external/L3_Lab_research_128x54/frame_4.png and b/assets/dolphin/external/L3_Lab_research_128x54/frame_4.png differ diff --git a/assets/dolphin/external/L3_Lab_research_128x54/frame_5.png b/assets/dolphin/external/L3_Lab_research_128x54/frame_5.png index 6853e1d61..697b307cb 100644 Binary files a/assets/dolphin/external/L3_Lab_research_128x54/frame_5.png and b/assets/dolphin/external/L3_Lab_research_128x54/frame_5.png differ diff --git a/assets/dolphin/external/L3_Lab_research_128x54/frame_6.png b/assets/dolphin/external/L3_Lab_research_128x54/frame_6.png index 9a92ba8d8..daa7667cc 100644 Binary files a/assets/dolphin/external/L3_Lab_research_128x54/frame_6.png and b/assets/dolphin/external/L3_Lab_research_128x54/frame_6.png differ diff --git a/assets/dolphin/external/L3_Lab_research_128x54/frame_7.png b/assets/dolphin/external/L3_Lab_research_128x54/frame_7.png index 910ae5852..03a672f63 100644 Binary files a/assets/dolphin/external/L3_Lab_research_128x54/frame_7.png and b/assets/dolphin/external/L3_Lab_research_128x54/frame_7.png differ diff --git a/assets/dolphin/external/L3_Lab_research_128x54/frame_8.png b/assets/dolphin/external/L3_Lab_research_128x54/frame_8.png index 0f681e6ab..6ed2507da 100644 Binary files a/assets/dolphin/external/L3_Lab_research_128x54/frame_8.png and b/assets/dolphin/external/L3_Lab_research_128x54/frame_8.png differ diff --git a/assets/dolphin/external/L3_Lab_research_128x54/frame_9.png b/assets/dolphin/external/L3_Lab_research_128x54/frame_9.png index 0f391b75e..6b237672e 100644 Binary files a/assets/dolphin/external/L3_Lab_research_128x54/frame_9.png and b/assets/dolphin/external/L3_Lab_research_128x54/frame_9.png differ diff --git a/assets/dolphin/internal/L1_AnimationError_128x64/frame_0.png b/assets/dolphin/internal/L1_AnimationError_128x64/frame_0.png index 8ea393cee..2da87f907 100644 Binary files a/assets/dolphin/internal/L1_AnimationError_128x64/frame_0.png and b/assets/dolphin/internal/L1_AnimationError_128x64/frame_0.png differ diff --git a/assets/dolphin/internal/L1_BadBattery_128x47/frame_0.png b/assets/dolphin/internal/L1_BadBattery_128x47/frame_0.png index 98c2979cf..d9c26f229 100644 Binary files a/assets/dolphin/internal/L1_BadBattery_128x47/frame_0.png and b/assets/dolphin/internal/L1_BadBattery_128x47/frame_0.png differ diff --git a/assets/dolphin/internal/L1_NoSd_128x49/frame_0.png b/assets/dolphin/internal/L1_NoSd_128x49/frame_0.png index 48528960e..5e1b8c01a 100644 Binary files a/assets/dolphin/internal/L1_NoSd_128x49/frame_0.png and b/assets/dolphin/internal/L1_NoSd_128x49/frame_0.png differ diff --git a/assets/icons/About/Certification1_103x56.png b/assets/icons/About/Certification1_103x56.png index 6e11bbbb2..ae6b4abe0 100644 Binary files a/assets/icons/About/Certification1_103x56.png and b/assets/icons/About/Certification1_103x56.png differ diff --git a/assets/icons/About/Certification2_46x33.png b/assets/icons/About/Certification2_46x33.png index d421b8291..32c98de58 100644 Binary files a/assets/icons/About/Certification2_46x33.png and b/assets/icons/About/Certification2_46x33.png differ diff --git a/assets/icons/About/CertificationChina0_121x41.png b/assets/icons/About/CertificationChina0_121x41.png index 1d28577ab..4202615f8 100644 Binary files a/assets/icons/About/CertificationChina0_121x41.png and b/assets/icons/About/CertificationChina0_121x41.png differ diff --git a/assets/icons/About/CertificationChina1_124x47.png b/assets/icons/About/CertificationChina1_124x47.png index f40f53394..a02e27c6c 100644 Binary files a/assets/icons/About/CertificationChina1_124x47.png and b/assets/icons/About/CertificationChina1_124x47.png differ diff --git a/assets/icons/About/CertificationMexico_98x41.png b/assets/icons/About/CertificationMexico_98x41.png index 9b1e45e6f..f4552d225 100644 Binary files a/assets/icons/About/CertificationMexico_98x41.png and b/assets/icons/About/CertificationMexico_98x41.png differ diff --git a/assets/icons/About/CertificationTaiwan_33x32.png b/assets/icons/About/CertificationTaiwan_33x32.png index bf2bfa21a..393db57c8 100644 Binary files a/assets/icons/About/CertificationTaiwan_33x32.png and b/assets/icons/About/CertificationTaiwan_33x32.png differ diff --git a/assets/icons/Animations/Levelup_128x64/frame_00.png b/assets/icons/Animations/Levelup_128x64/frame_00.png index 77b531076..bcf751e74 100644 Binary files a/assets/icons/Animations/Levelup_128x64/frame_00.png and b/assets/icons/Animations/Levelup_128x64/frame_00.png differ diff --git a/assets/icons/Animations/Levelup_128x64/frame_01.png b/assets/icons/Animations/Levelup_128x64/frame_01.png index b53437265..8278a98f2 100644 Binary files a/assets/icons/Animations/Levelup_128x64/frame_01.png and b/assets/icons/Animations/Levelup_128x64/frame_01.png differ diff --git a/assets/icons/Animations/Levelup_128x64/frame_02.png b/assets/icons/Animations/Levelup_128x64/frame_02.png index 9623af7d8..2c8875ad1 100644 Binary files a/assets/icons/Animations/Levelup_128x64/frame_02.png and b/assets/icons/Animations/Levelup_128x64/frame_02.png differ diff --git a/assets/icons/Animations/Levelup_128x64/frame_03.png b/assets/icons/Animations/Levelup_128x64/frame_03.png index f18269019..deeff97c5 100644 Binary files a/assets/icons/Animations/Levelup_128x64/frame_03.png and b/assets/icons/Animations/Levelup_128x64/frame_03.png differ diff --git a/assets/icons/Animations/Levelup_128x64/frame_04.png b/assets/icons/Animations/Levelup_128x64/frame_04.png index 677a3367e..366b8555c 100644 Binary files a/assets/icons/Animations/Levelup_128x64/frame_04.png and b/assets/icons/Animations/Levelup_128x64/frame_04.png differ diff --git a/assets/icons/Animations/Levelup_128x64/frame_05.png b/assets/icons/Animations/Levelup_128x64/frame_05.png index fb58fed1e..a033448f7 100644 Binary files a/assets/icons/Animations/Levelup_128x64/frame_05.png and b/assets/icons/Animations/Levelup_128x64/frame_05.png differ diff --git a/assets/icons/Animations/Levelup_128x64/frame_06.png b/assets/icons/Animations/Levelup_128x64/frame_06.png index b2cbd699b..4e77c6a2b 100644 Binary files a/assets/icons/Animations/Levelup_128x64/frame_06.png and b/assets/icons/Animations/Levelup_128x64/frame_06.png differ diff --git a/assets/icons/Animations/Levelup_128x64/frame_07.png b/assets/icons/Animations/Levelup_128x64/frame_07.png index 4f3dfc8c4..52fd56d31 100644 Binary files a/assets/icons/Animations/Levelup_128x64/frame_07.png and b/assets/icons/Animations/Levelup_128x64/frame_07.png differ diff --git a/assets/icons/Animations/Levelup_128x64/frame_08.png b/assets/icons/Animations/Levelup_128x64/frame_08.png index 3a5a28805..2c3aae26b 100644 Binary files a/assets/icons/Animations/Levelup_128x64/frame_08.png and b/assets/icons/Animations/Levelup_128x64/frame_08.png differ diff --git a/assets/icons/Animations/Levelup_128x64/frame_09.png b/assets/icons/Animations/Levelup_128x64/frame_09.png index 76267a2a8..27babdfec 100644 Binary files a/assets/icons/Animations/Levelup_128x64/frame_09.png and b/assets/icons/Animations/Levelup_128x64/frame_09.png differ diff --git a/assets/icons/Animations/Levelup_128x64/frame_10.png b/assets/icons/Animations/Levelup_128x64/frame_10.png index bda1bf44c..0d2ae19ae 100644 Binary files a/assets/icons/Animations/Levelup_128x64/frame_10.png and b/assets/icons/Animations/Levelup_128x64/frame_10.png differ diff --git a/assets/icons/Archive/125_10px.png b/assets/icons/Archive/125_10px.png index ce01284a2..fd3947ff3 100644 Binary files a/assets/icons/Archive/125_10px.png and b/assets/icons/Archive/125_10px.png differ diff --git a/assets/icons/Archive/Apps_10px.png b/assets/icons/Archive/Apps_10px.png index cb3a2e688..2712c6ba2 100644 Binary files a/assets/icons/Archive/Apps_10px.png and b/assets/icons/Archive/Apps_10px.png differ diff --git a/assets/icons/Archive/Nfc_10px.png b/assets/icons/Archive/Nfc_10px.png index 6bc027111..e998d291e 100644 Binary files a/assets/icons/Archive/Nfc_10px.png and b/assets/icons/Archive/Nfc_10px.png differ diff --git a/assets/icons/Archive/back_10px.png b/assets/icons/Archive/back_10px.png index f9c615a99..b7ffd4efb 100644 Binary files a/assets/icons/Archive/back_10px.png and b/assets/icons/Archive/back_10px.png differ diff --git a/assets/icons/Archive/badkb_10px.png b/assets/icons/Archive/badkb_10px.png index 037474aa3..2b5a3bf97 100644 Binary files a/assets/icons/Archive/badkb_10px.png and b/assets/icons/Archive/badkb_10px.png differ diff --git a/assets/icons/Archive/dir_10px.png b/assets/icons/Archive/dir_10px.png index a4cdf453e..1b64022c2 100644 Binary files a/assets/icons/Archive/dir_10px.png and b/assets/icons/Archive/dir_10px.png differ diff --git a/assets/icons/Archive/file_10px.png b/assets/icons/Archive/file_10px.png index 8e8a6183d..cd38770f4 100644 Binary files a/assets/icons/Archive/file_10px.png and b/assets/icons/Archive/file_10px.png differ diff --git a/assets/icons/Archive/floppydisk_10px.png b/assets/icons/Archive/floppydisk_10px.png index 91af40ba7..c00ccf82f 100644 Binary files a/assets/icons/Archive/floppydisk_10px.png and b/assets/icons/Archive/floppydisk_10px.png differ diff --git a/assets/icons/Archive/ibutt_10px.png b/assets/icons/Archive/ibutt_10px.png index 2fdaf123a..f73af065f 100644 Binary files a/assets/icons/Archive/ibutt_10px.png and b/assets/icons/Archive/ibutt_10px.png differ diff --git a/assets/icons/Archive/ir_10px.png b/assets/icons/Archive/ir_10px.png index 22c986180..36c214f3b 100644 Binary files a/assets/icons/Archive/ir_10px.png and b/assets/icons/Archive/ir_10px.png differ diff --git a/assets/icons/Archive/ir_scope_10px.png b/assets/icons/Archive/ir_scope_10px.png index c0d7eaba0..4dbf3ae04 100644 Binary files a/assets/icons/Archive/ir_scope_10px.png and b/assets/icons/Archive/ir_scope_10px.png differ diff --git a/assets/icons/Archive/js_script_10px.png b/assets/icons/Archive/js_script_10px.png index 77ac76337..48210a049 100644 Binary files a/assets/icons/Archive/js_script_10px.png and b/assets/icons/Archive/js_script_10px.png differ diff --git a/assets/icons/Archive/keyboard_10px.png b/assets/icons/Archive/keyboard_10px.png index 74a10e6db..dc3e3cee2 100644 Binary files a/assets/icons/Archive/keyboard_10px.png and b/assets/icons/Archive/keyboard_10px.png differ diff --git a/assets/icons/Archive/loading_10px.png b/assets/icons/Archive/loading_10px.png index 4f626b3d5..a6065b6c0 100644 Binary files a/assets/icons/Archive/loading_10px.png and b/assets/icons/Archive/loading_10px.png differ diff --git a/assets/icons/Archive/mag_card_10px.png b/assets/icons/Archive/mag_card_10px.png index 28d683d82..00acb56d7 100644 Binary files a/assets/icons/Archive/mag_card_10px.png and b/assets/icons/Archive/mag_card_10px.png differ diff --git a/assets/icons/Archive/music_10px.png b/assets/icons/Archive/music_10px.png index d41eb0db8..98fed6d92 100644 Binary files a/assets/icons/Archive/music_10px.png and b/assets/icons/Archive/music_10px.png differ diff --git a/assets/icons/Archive/search_10px.png b/assets/icons/Archive/search_10px.png index 6b5211074..f48c8fbdd 100644 Binary files a/assets/icons/Archive/search_10px.png and b/assets/icons/Archive/search_10px.png differ diff --git a/assets/icons/Archive/sub1_10px.png b/assets/icons/Archive/sub1_10px.png index 5a25fdf4e..70940ad77 100644 Binary files a/assets/icons/Archive/sub1_10px.png and b/assets/icons/Archive/sub1_10px.png differ diff --git a/assets/icons/Archive/subplaylist_10px.png b/assets/icons/Archive/subplaylist_10px.png index 3d3f1d27f..43b126d42 100644 Binary files a/assets/icons/Archive/subplaylist_10px.png and b/assets/icons/Archive/subplaylist_10px.png differ diff --git a/assets/icons/Archive/subrem_10px.png b/assets/icons/Archive/subrem_10px.png index c6b410f4c..d99e0d1f6 100644 Binary files a/assets/icons/Archive/subrem_10px.png and b/assets/icons/Archive/subrem_10px.png differ diff --git a/assets/icons/Archive/u2f_10px.png b/assets/icons/Archive/u2f_10px.png index fcd87a2ef..6f46b0e78 100644 Binary files a/assets/icons/Archive/u2f_10px.png and b/assets/icons/Archive/u2f_10px.png differ diff --git a/assets/icons/Archive/unknown_10px.png b/assets/icons/Archive/unknown_10px.png index 18d31c67c..2d2668e85 100644 Binary files a/assets/icons/Archive/unknown_10px.png and b/assets/icons/Archive/unknown_10px.png differ diff --git a/assets/icons/Archive/update_10px.png b/assets/icons/Archive/update_10px.png index 5a97651c4..94c96769f 100644 Binary files a/assets/icons/Archive/update_10px.png and b/assets/icons/Archive/update_10px.png differ diff --git a/assets/icons/BLE/BLE_HID/Ble_connected_15x15.png b/assets/icons/BLE/BLE_HID/Ble_connected_15x15.png index 64dab9b53..1301399da 100644 Binary files a/assets/icons/BLE/BLE_HID/Ble_connected_15x15.png and b/assets/icons/BLE/BLE_HID/Ble_connected_15x15.png differ diff --git a/assets/icons/BLE/BLE_HID/Ble_disconnected_15x15.png b/assets/icons/BLE/BLE_HID/Ble_disconnected_15x15.png index 6bb499268..f926ce212 100644 Binary files a/assets/icons/BLE/BLE_HID/Ble_disconnected_15x15.png and b/assets/icons/BLE/BLE_HID/Ble_disconnected_15x15.png differ diff --git a/assets/icons/BLE/BLE_HID/Button_18x18.png b/assets/icons/BLE/BLE_HID/Button_18x18.png index 30a5b4fab..2334dd8be 100644 Binary files a/assets/icons/BLE/BLE_HID/Button_18x18.png and b/assets/icons/BLE/BLE_HID/Button_18x18.png differ diff --git a/assets/icons/BLE/BLE_HID/Circles_47x47.png b/assets/icons/BLE/BLE_HID/Circles_47x47.png index 6a16ebf7b..bf72412f5 100644 Binary files a/assets/icons/BLE/BLE_HID/Circles_47x47.png and b/assets/icons/BLE/BLE_HID/Circles_47x47.png differ diff --git a/assets/icons/BLE/BLE_HID/Left_mouse_icon_9x9.png b/assets/icons/BLE/BLE_HID/Left_mouse_icon_9x9.png index c533d8572..5bd2d395f 100644 Binary files a/assets/icons/BLE/BLE_HID/Left_mouse_icon_9x9.png and b/assets/icons/BLE/BLE_HID/Left_mouse_icon_9x9.png differ diff --git a/assets/icons/BLE/BLE_HID/Ok_btn_9x9.png b/assets/icons/BLE/BLE_HID/Ok_btn_9x9.png index 9a1539da2..ceff4e8a8 100644 Binary files a/assets/icons/BLE/BLE_HID/Ok_btn_9x9.png and b/assets/icons/BLE/BLE_HID/Ok_btn_9x9.png differ diff --git a/assets/icons/BLE/BLE_HID/Ok_btn_pressed_13x13.png b/assets/icons/BLE/BLE_HID/Ok_btn_pressed_13x13.png index 6b46ba3a8..ced2369b4 100644 Binary files a/assets/icons/BLE/BLE_HID/Ok_btn_pressed_13x13.png and b/assets/icons/BLE/BLE_HID/Ok_btn_pressed_13x13.png differ diff --git a/assets/icons/BLE/BLE_HID/Pressed_Button_13x13.png b/assets/icons/BLE/BLE_HID/Pressed_Button_13x13.png index 823926b84..d0e2c3a37 100644 Binary files a/assets/icons/BLE/BLE_HID/Pressed_Button_13x13.png and b/assets/icons/BLE/BLE_HID/Pressed_Button_13x13.png differ diff --git a/assets/icons/BLE/BLE_HID/Right_mouse_icon_9x9.png b/assets/icons/BLE/BLE_HID/Right_mouse_icon_9x9.png index 446d7176c..1da29ee43 100644 Binary files a/assets/icons/BLE/BLE_HID/Right_mouse_icon_9x9.png and b/assets/icons/BLE/BLE_HID/Right_mouse_icon_9x9.png differ diff --git a/assets/icons/BLE/BLE_HID/Space_65x18.png b/assets/icons/BLE/BLE_HID/Space_65x18.png index b60ae5097..eb417f674 100644 Binary files a/assets/icons/BLE/BLE_HID/Space_65x18.png and b/assets/icons/BLE/BLE_HID/Space_65x18.png differ diff --git a/assets/icons/BLE/BLE_HID/Voldwn_6x6.png b/assets/icons/BLE/BLE_HID/Voldwn_6x6.png index d7a82a2df..d6d7e286a 100644 Binary files a/assets/icons/BLE/BLE_HID/Voldwn_6x6.png and b/assets/icons/BLE/BLE_HID/Voldwn_6x6.png differ diff --git a/assets/icons/BLE/BLE_HID/Volup_8x6.png b/assets/icons/BLE/BLE_HID/Volup_8x6.png index 4b7ec66d6..66477bc7b 100644 Binary files a/assets/icons/BLE/BLE_HID/Volup_8x6.png and b/assets/icons/BLE/BLE_HID/Volup_8x6.png differ diff --git a/assets/icons/BLE/BLE_Pairing_128x64.png b/assets/icons/BLE/BLE_Pairing_128x64.png index 34068c300..97800403f 100644 Binary files a/assets/icons/BLE/BLE_Pairing_128x64.png and b/assets/icons/BLE/BLE_Pairing_128x64.png differ diff --git a/assets/icons/BadKb/Clock_18x18.png b/assets/icons/BadKb/Clock_18x18.png index ab06d008e..71ba0274f 100644 Binary files a/assets/icons/BadKb/Clock_18x18.png and b/assets/icons/BadKb/Clock_18x18.png differ diff --git a/assets/icons/BadKb/Error_18x18.png b/assets/icons/BadKb/Error_18x18.png index 16a5a74d9..28de03da8 100644 Binary files a/assets/icons/BadKb/Error_18x18.png and b/assets/icons/BadKb/Error_18x18.png differ diff --git a/assets/icons/BadKb/EviSmile1_18x21.png b/assets/icons/BadKb/EviSmile1_18x21.png index 987af3258..1ba168c61 100644 Binary files a/assets/icons/BadKb/EviSmile1_18x21.png and b/assets/icons/BadKb/EviSmile1_18x21.png differ diff --git a/assets/icons/BadKb/EviSmile2_18x21.png b/assets/icons/BadKb/EviSmile2_18x21.png index 7e28c9f01..0318d425a 100644 Binary files a/assets/icons/BadKb/EviSmile2_18x21.png and b/assets/icons/BadKb/EviSmile2_18x21.png differ diff --git a/assets/icons/BadKb/EviWaiting1_18x21.png b/assets/icons/BadKb/EviWaiting1_18x21.png index d39d21733..82fc0f330 100644 Binary files a/assets/icons/BadKb/EviWaiting1_18x21.png and b/assets/icons/BadKb/EviWaiting1_18x21.png differ diff --git a/assets/icons/BadKb/EviWaiting2_18x21.png b/assets/icons/BadKb/EviWaiting2_18x21.png index 15ca088fd..7209d3581 100644 Binary files a/assets/icons/BadKb/EviWaiting2_18x21.png and b/assets/icons/BadKb/EviWaiting2_18x21.png differ diff --git a/assets/icons/BadKb/Percent_10x14.png b/assets/icons/BadKb/Percent_10x14.png index 677911fd4..97b304f1a 100644 Binary files a/assets/icons/BadKb/Percent_10x14.png and b/assets/icons/BadKb/Percent_10x14.png differ diff --git a/assets/icons/BadKb/Smile_18x18.png b/assets/icons/BadKb/Smile_18x18.png index d2aae0dc3..c0ff50c0b 100644 Binary files a/assets/icons/BadKb/Smile_18x18.png and b/assets/icons/BadKb/Smile_18x18.png differ diff --git a/assets/icons/BadKb/UsbTree_48x22.png b/assets/icons/BadKb/UsbTree_48x22.png index cc41b5b9a..33ce1bf5a 100644 Binary files a/assets/icons/BadKb/UsbTree_48x22.png and b/assets/icons/BadKb/UsbTree_48x22.png differ diff --git a/assets/icons/Common/ActiveConnection_50x64.png b/assets/icons/Common/ActiveConnection_50x64.png index 1d7686ddd..c5ebb8352 100644 Binary files a/assets/icons/Common/ActiveConnection_50x64.png and b/assets/icons/Common/ActiveConnection_50x64.png differ diff --git a/assets/icons/Common/ButtonCenter_7x7.png b/assets/icons/Common/ButtonCenter_7x7.png index a66461b22..e1e015ab5 100644 Binary files a/assets/icons/Common/ButtonCenter_7x7.png and b/assets/icons/Common/ButtonCenter_7x7.png differ diff --git a/assets/icons/Common/ButtonDown_7x4.png b/assets/icons/Common/ButtonDown_7x4.png index 2954bb6a6..0cda838e0 100644 Binary files a/assets/icons/Common/ButtonDown_7x4.png and b/assets/icons/Common/ButtonDown_7x4.png differ diff --git a/assets/icons/Common/ButtonLeftSmall_3x5.png b/assets/icons/Common/ButtonLeftSmall_3x5.png index 51411acaf..0fb7fb313 100644 Binary files a/assets/icons/Common/ButtonLeftSmall_3x5.png and b/assets/icons/Common/ButtonLeftSmall_3x5.png differ diff --git a/assets/icons/Common/ButtonLeft_4x7.png b/assets/icons/Common/ButtonLeft_4x7.png index 0b4655d43..7c43f3b04 100644 Binary files a/assets/icons/Common/ButtonLeft_4x7.png and b/assets/icons/Common/ButtonLeft_4x7.png differ diff --git a/assets/icons/Common/ButtonRightSmall_3x5.png b/assets/icons/Common/ButtonRightSmall_3x5.png index b9d5f87db..c25ba7261 100644 Binary files a/assets/icons/Common/ButtonRightSmall_3x5.png and b/assets/icons/Common/ButtonRightSmall_3x5.png differ diff --git a/assets/icons/Common/ButtonRight_4x7.png b/assets/icons/Common/ButtonRight_4x7.png index 8e1c74c1c..31de21c0e 100644 Binary files a/assets/icons/Common/ButtonRight_4x7.png and b/assets/icons/Common/ButtonRight_4x7.png differ diff --git a/assets/icons/Common/ButtonUp_7x4.png b/assets/icons/Common/ButtonUp_7x4.png index 1be79328b..48d0f9f01 100644 Binary files a/assets/icons/Common/ButtonUp_7x4.png and b/assets/icons/Common/ButtonUp_7x4.png differ diff --git a/assets/icons/Common/DFU_128x50.png b/assets/icons/Common/DFU_128x50.png index 6916d558e..abe2d9fa5 100644 Binary files a/assets/icons/Common/DFU_128x50.png and b/assets/icons/Common/DFU_128x50.png differ diff --git a/assets/icons/Common/Hashmark_7x7.png b/assets/icons/Common/Hashmark_7x7.png index 93fb147be..6ede005dd 100644 Binary files a/assets/icons/Common/Hashmark_7x7.png and b/assets/icons/Common/Hashmark_7x7.png differ diff --git a/assets/icons/Common/Loading_24/frame_01.png b/assets/icons/Common/Loading_24/frame_01.png index 9c49dcad1..7fafe05ca 100644 Binary files a/assets/icons/Common/Loading_24/frame_01.png and b/assets/icons/Common/Loading_24/frame_01.png differ diff --git a/assets/icons/Common/Loading_24/frame_02.png b/assets/icons/Common/Loading_24/frame_02.png index 93a59fe68..8684b4f34 100644 Binary files a/assets/icons/Common/Loading_24/frame_02.png and b/assets/icons/Common/Loading_24/frame_02.png differ diff --git a/assets/icons/Common/Loading_24/frame_03.png b/assets/icons/Common/Loading_24/frame_03.png index 7bb66fca0..01c99c56e 100644 Binary files a/assets/icons/Common/Loading_24/frame_03.png and b/assets/icons/Common/Loading_24/frame_03.png differ diff --git a/assets/icons/Common/Loading_24/frame_04.png b/assets/icons/Common/Loading_24/frame_04.png index adefde921..15019fbc6 100644 Binary files a/assets/icons/Common/Loading_24/frame_04.png and b/assets/icons/Common/Loading_24/frame_04.png differ diff --git a/assets/icons/Common/Loading_24/frame_05.png b/assets/icons/Common/Loading_24/frame_05.png index 80bf88e96..c144a72ed 100644 Binary files a/assets/icons/Common/Loading_24/frame_05.png and b/assets/icons/Common/Loading_24/frame_05.png differ diff --git a/assets/icons/Common/Loading_24/frame_06.png b/assets/icons/Common/Loading_24/frame_06.png index b768a7875..fe66f11c6 100644 Binary files a/assets/icons/Common/Loading_24/frame_06.png and b/assets/icons/Common/Loading_24/frame_06.png differ diff --git a/assets/icons/Common/Loading_24/frame_07.png b/assets/icons/Common/Loading_24/frame_07.png index 190d2edf3..a7843a35b 100644 Binary files a/assets/icons/Common/Loading_24/frame_07.png and b/assets/icons/Common/Loading_24/frame_07.png differ diff --git a/assets/icons/Common/More_data_placeholder_5x7.png b/assets/icons/Common/More_data_placeholder_5x7.png index 85025d9f0..bbfdae047 100644 Binary files a/assets/icons/Common/More_data_placeholder_5x7.png and b/assets/icons/Common/More_data_placeholder_5x7.png differ diff --git a/assets/icons/Common/Round_loader_8x8/frame_01.png b/assets/icons/Common/Round_loader_8x8/frame_01.png index a5dc239d8..b8db2a4b5 100644 Binary files a/assets/icons/Common/Round_loader_8x8/frame_01.png and b/assets/icons/Common/Round_loader_8x8/frame_01.png differ diff --git a/assets/icons/Common/Round_loader_8x8/frame_02.png b/assets/icons/Common/Round_loader_8x8/frame_02.png index 162d8a8f4..aa0f22a4c 100644 Binary files a/assets/icons/Common/Round_loader_8x8/frame_02.png and b/assets/icons/Common/Round_loader_8x8/frame_02.png differ diff --git a/assets/icons/Common/Round_loader_8x8/frame_03.png b/assets/icons/Common/Round_loader_8x8/frame_03.png index 5483e4734..cba466ef6 100644 Binary files a/assets/icons/Common/Round_loader_8x8/frame_03.png and b/assets/icons/Common/Round_loader_8x8/frame_03.png differ diff --git a/assets/icons/Common/Round_loader_8x8/frame_04.png b/assets/icons/Common/Round_loader_8x8/frame_04.png index ce2fbbd47..4e90ed650 100644 Binary files a/assets/icons/Common/Round_loader_8x8/frame_04.png and b/assets/icons/Common/Round_loader_8x8/frame_04.png differ diff --git a/assets/icons/Common/Round_loader_8x8/frame_05.png b/assets/icons/Common/Round_loader_8x8/frame_05.png index 8b786c029..ed319f764 100644 Binary files a/assets/icons/Common/Round_loader_8x8/frame_05.png and b/assets/icons/Common/Round_loader_8x8/frame_05.png differ diff --git a/assets/icons/Common/Warning_30x23.png b/assets/icons/Common/Warning_30x23.png index 5f7e02dd8..f307436f5 100644 Binary files a/assets/icons/Common/Warning_30x23.png and b/assets/icons/Common/Warning_30x23.png differ diff --git a/assets/icons/Common/arrow_nano_down.png b/assets/icons/Common/arrow_nano_down.png index da66350bd..244b022a5 100644 Binary files a/assets/icons/Common/arrow_nano_down.png and b/assets/icons/Common/arrow_nano_down.png differ diff --git a/assets/icons/Common/arrow_nano_up.png b/assets/icons/Common/arrow_nano_up.png index 4a1d5be85..ccaf88b6e 100644 Binary files a/assets/icons/Common/arrow_nano_up.png and b/assets/icons/Common/arrow_nano_up.png differ diff --git a/assets/icons/ControlCenter/CC_Bluetooth_16x16.png b/assets/icons/ControlCenter/CC_Bluetooth_16x16.png index 67d642d47..1c3a687f7 100644 Binary files a/assets/icons/ControlCenter/CC_Bluetooth_16x16.png and b/assets/icons/ControlCenter/CC_Bluetooth_16x16.png differ diff --git a/assets/icons/ControlCenter/CC_DarkMode_16x16.png b/assets/icons/ControlCenter/CC_DarkMode_16x16.png index c2b7390a9..274bc9e23 100644 Binary files a/assets/icons/ControlCenter/CC_DarkMode_16x16.png and b/assets/icons/ControlCenter/CC_DarkMode_16x16.png differ diff --git a/assets/icons/ControlCenter/CC_LefthandedMode_16x16.png b/assets/icons/ControlCenter/CC_LefthandedMode_16x16.png index 1f8b4ca48..d7f082c07 100644 Binary files a/assets/icons/ControlCenter/CC_LefthandedMode_16x16.png and b/assets/icons/ControlCenter/CC_LefthandedMode_16x16.png differ diff --git a/assets/icons/ControlCenter/CC_Lock_16x16.png b/assets/icons/ControlCenter/CC_Lock_16x16.png index 13d5efcad..69d2a0014 100644 Binary files a/assets/icons/ControlCenter/CC_Lock_16x16.png and b/assets/icons/ControlCenter/CC_Lock_16x16.png differ diff --git a/assets/icons/ControlCenter/CC_Momentum_16x16.png b/assets/icons/ControlCenter/CC_Momentum_16x16.png index 164a13b2d..50745d39c 100644 Binary files a/assets/icons/ControlCenter/CC_Momentum_16x16.png and b/assets/icons/ControlCenter/CC_Momentum_16x16.png differ diff --git a/assets/icons/ControlCenter/CC_Settings_16x16.png b/assets/icons/ControlCenter/CC_Settings_16x16.png index defc2e41d..9e788ea6d 100644 Binary files a/assets/icons/ControlCenter/CC_Settings_16x16.png and b/assets/icons/ControlCenter/CC_Settings_16x16.png differ diff --git a/assets/icons/Dolphin/DolphinDone_80x58.png b/assets/icons/Dolphin/DolphinDone_80x58.png index 594d62d52..881aaa8d2 100644 Binary files a/assets/icons/Dolphin/DolphinDone_80x58.png and b/assets/icons/Dolphin/DolphinDone_80x58.png differ diff --git a/assets/icons/Dolphin/DolphinMafia_119x62.png b/assets/icons/Dolphin/DolphinMafia_119x62.png index 1bbbec84a..4d47ed5b1 100644 Binary files a/assets/icons/Dolphin/DolphinMafia_119x62.png and b/assets/icons/Dolphin/DolphinMafia_119x62.png differ diff --git a/assets/icons/Dolphin/DolphinReadingSuccess_59x63.png b/assets/icons/Dolphin/DolphinReadingSuccess_59x63.png index 46f559f65..1380d2dd7 100644 Binary files a/assets/icons/Dolphin/DolphinReadingSuccess_59x63.png and b/assets/icons/Dolphin/DolphinReadingSuccess_59x63.png differ diff --git a/assets/icons/Dolphin/DolphinSaved_92x58.png b/assets/icons/Dolphin/DolphinSaved_92x58.png index e8704295c..45da01480 100644 Binary files a/assets/icons/Dolphin/DolphinSaved_92x58.png and b/assets/icons/Dolphin/DolphinSaved_92x58.png differ diff --git a/assets/icons/Dolphin/DolphinSuccess_91x55.png b/assets/icons/Dolphin/DolphinSuccess_91x55.png index 80caeb203..1dc514db6 100644 Binary files a/assets/icons/Dolphin/DolphinSuccess_91x55.png and b/assets/icons/Dolphin/DolphinSuccess_91x55.png differ diff --git a/assets/icons/Dolphin/DolphinWait_59x54.png b/assets/icons/Dolphin/DolphinWait_59x54.png index bdf8171b8..b906916d2 100644 Binary files a/assets/icons/Dolphin/DolphinWait_59x54.png and b/assets/icons/Dolphin/DolphinWait_59x54.png differ diff --git a/assets/icons/Dolphin/WarningDolphinFlip_45x42.png b/assets/icons/Dolphin/WarningDolphinFlip_45x42.png index 2ba54afce..a2554eaa6 100644 Binary files a/assets/icons/Dolphin/WarningDolphinFlip_45x42.png and b/assets/icons/Dolphin/WarningDolphinFlip_45x42.png differ diff --git a/assets/icons/Dolphin/WarningDolphin_45x42.png b/assets/icons/Dolphin/WarningDolphin_45x42.png index d766ffbb4..310be0f70 100644 Binary files a/assets/icons/Dolphin/WarningDolphin_45x42.png and b/assets/icons/Dolphin/WarningDolphin_45x42.png differ diff --git a/assets/icons/ErasePin/Erase_pin_128x64.png b/assets/icons/ErasePin/Erase_pin_128x64.png index ee1eefe7a..4e2a9ddc8 100644 Binary files a/assets/icons/ErasePin/Erase_pin_128x64.png and b/assets/icons/ErasePin/Erase_pin_128x64.png differ diff --git a/assets/icons/GPIO/ArrowUpEmpty_14x15.png b/assets/icons/GPIO/ArrowUpEmpty_14x15.png index 261c6d89e..01209712e 100644 Binary files a/assets/icons/GPIO/ArrowUpEmpty_14x15.png and b/assets/icons/GPIO/ArrowUpEmpty_14x15.png differ diff --git a/assets/icons/GPIO/ArrowUpFilled_14x15.png b/assets/icons/GPIO/ArrowUpFilled_14x15.png index fa35eb2f8..2c6dfd9cc 100644 Binary files a/assets/icons/GPIO/ArrowUpFilled_14x15.png and b/assets/icons/GPIO/ArrowUpFilled_14x15.png differ diff --git a/assets/icons/Infrared/InfraredArrowDown_4x8.png b/assets/icons/Infrared/InfraredArrowDown_4x8.png index 2ac7bcdbe..086fa43fb 100644 Binary files a/assets/icons/Infrared/InfraredArrowDown_4x8.png and b/assets/icons/Infrared/InfraredArrowDown_4x8.png differ diff --git a/assets/icons/Infrared/InfraredArrowUp_4x8.png b/assets/icons/Infrared/InfraredArrowUp_4x8.png index 4c9a16b3f..1be28a53a 100644 Binary files a/assets/icons/Infrared/InfraredArrowUp_4x8.png and b/assets/icons/Infrared/InfraredArrowUp_4x8.png differ diff --git a/assets/icons/Infrared/InfraredLearnShort_128x31.png b/assets/icons/Infrared/InfraredLearnShort_128x31.png index 783ad0877..41d9cdfc7 100644 Binary files a/assets/icons/Infrared/InfraredLearnShort_128x31.png and b/assets/icons/Infrared/InfraredLearnShort_128x31.png differ diff --git a/assets/icons/Infrared/Play_25x27.png b/assets/icons/Infrared/Play_25x27.png index de4af2232..f1064d7b1 100644 Binary files a/assets/icons/Infrared/Play_25x27.png and b/assets/icons/Infrared/Play_25x27.png differ diff --git a/assets/icons/Infrared/Play_hvr_25x27.png b/assets/icons/Infrared/Play_hvr_25x27.png index 2a8eb97d0..fa234ba17 100644 Binary files a/assets/icons/Infrared/Play_hvr_25x27.png and b/assets/icons/Infrared/Play_hvr_25x27.png differ diff --git a/assets/icons/Infrared/bright_text_30x30.png b/assets/icons/Infrared/bright_text_30x30.png index 90275124c..974e47abc 100644 Binary files a/assets/icons/Infrared/bright_text_30x30.png and b/assets/icons/Infrared/bright_text_30x30.png differ diff --git a/assets/icons/Infrared/celsius_24x23.png b/assets/icons/Infrared/celsius_24x23.png index 64d7a1db1..9a6c30c75 100644 Binary files a/assets/icons/Infrared/celsius_24x23.png and b/assets/icons/Infrared/celsius_24x23.png differ diff --git a/assets/icons/Infrared/celsius_hover_24x23.png b/assets/icons/Infrared/celsius_hover_24x23.png index 0488b40f5..f5eb3f4bd 100644 Binary files a/assets/icons/Infrared/celsius_hover_24x23.png and b/assets/icons/Infrared/celsius_hover_24x23.png differ diff --git a/assets/icons/Infrared/ch_down_24x21.png b/assets/icons/Infrared/ch_down_24x21.png index 8c3f81c3d..a3803c745 100644 Binary files a/assets/icons/Infrared/ch_down_24x21.png and b/assets/icons/Infrared/ch_down_24x21.png differ diff --git a/assets/icons/Infrared/ch_down_hover_24x21.png b/assets/icons/Infrared/ch_down_hover_24x21.png index 9b840f9ce..5320c82a7 100644 Binary files a/assets/icons/Infrared/ch_down_hover_24x21.png and b/assets/icons/Infrared/ch_down_hover_24x21.png differ diff --git a/assets/icons/Infrared/ch_text_31x34.png b/assets/icons/Infrared/ch_text_31x34.png index 30e0f584c..88f5c3890 100644 Binary files a/assets/icons/Infrared/ch_text_31x34.png and b/assets/icons/Infrared/ch_text_31x34.png differ diff --git a/assets/icons/Infrared/ch_up_24x21.png b/assets/icons/Infrared/ch_up_24x21.png index fa4074d12..356d124f6 100644 Binary files a/assets/icons/Infrared/ch_up_24x21.png and b/assets/icons/Infrared/ch_up_24x21.png differ diff --git a/assets/icons/Infrared/ch_up_hover_24x21.png b/assets/icons/Infrared/ch_up_hover_24x21.png index 944a973f4..bef0ab0cc 100644 Binary files a/assets/icons/Infrared/ch_up_hover_24x21.png and b/assets/icons/Infrared/ch_up_hover_24x21.png differ diff --git a/assets/icons/Infrared/cool_30x51.png b/assets/icons/Infrared/cool_30x51.png index 38a8014bd..5dd42782d 100644 Binary files a/assets/icons/Infrared/cool_30x51.png and b/assets/icons/Infrared/cool_30x51.png differ diff --git a/assets/icons/Infrared/dry_19x20.png b/assets/icons/Infrared/dry_19x20.png index c689c0675..aab1e650f 100644 Binary files a/assets/icons/Infrared/dry_19x20.png and b/assets/icons/Infrared/dry_19x20.png differ diff --git a/assets/icons/Infrared/dry_hover_19x20.png b/assets/icons/Infrared/dry_hover_19x20.png index 5b7196ae2..5cd1a2814 100644 Binary files a/assets/icons/Infrared/dry_hover_19x20.png and b/assets/icons/Infrared/dry_hover_19x20.png differ diff --git a/assets/icons/Infrared/dry_text_15x5.png b/assets/icons/Infrared/dry_text_15x5.png index 7696e1fc8..49e2d4ab5 100644 Binary files a/assets/icons/Infrared/dry_text_15x5.png and b/assets/icons/Infrared/dry_text_15x5.png differ diff --git a/assets/icons/Infrared/exit_19x20.png b/assets/icons/Infrared/exit_19x20.png index b9356afa2..4eb85fd17 100644 Binary files a/assets/icons/Infrared/exit_19x20.png and b/assets/icons/Infrared/exit_19x20.png differ diff --git a/assets/icons/Infrared/exit_hover_19x20.png b/assets/icons/Infrared/exit_hover_19x20.png index 91700ee61..2d121d136 100644 Binary files a/assets/icons/Infrared/exit_hover_19x20.png and b/assets/icons/Infrared/exit_hover_19x20.png differ diff --git a/assets/icons/Infrared/exit_text_18x5.png b/assets/icons/Infrared/exit_text_18x5.png index f742de57d..2614e4f5f 100644 Binary files a/assets/icons/Infrared/exit_text_18x5.png and b/assets/icons/Infrared/exit_text_18x5.png differ diff --git a/assets/icons/Infrared/fahren_24x23.png b/assets/icons/Infrared/fahren_24x23.png index d6f55e806..df6ce92cf 100644 Binary files a/assets/icons/Infrared/fahren_24x23.png and b/assets/icons/Infrared/fahren_24x23.png differ diff --git a/assets/icons/Infrared/fahren_hover_24x23.png b/assets/icons/Infrared/fahren_hover_24x23.png index db922c557..9a1f73a08 100644 Binary files a/assets/icons/Infrared/fahren_hover_24x23.png and b/assets/icons/Infrared/fahren_hover_24x23.png differ diff --git a/assets/icons/Infrared/flash_19x20.png b/assets/icons/Infrared/flash_19x20.png index 205363f17..4fde611f1 100644 Binary files a/assets/icons/Infrared/flash_19x20.png and b/assets/icons/Infrared/flash_19x20.png differ diff --git a/assets/icons/Infrared/flash_hover_19x20.png b/assets/icons/Infrared/flash_hover_19x20.png index 31cd75039..acc5c0cf6 100644 Binary files a/assets/icons/Infrared/flash_hover_19x20.png and b/assets/icons/Infrared/flash_hover_19x20.png differ diff --git a/assets/icons/Infrared/flash_text_21x5.png b/assets/icons/Infrared/flash_text_21x5.png index 817a45808..9bf8eeac5 100644 Binary files a/assets/icons/Infrared/flash_text_21x5.png and b/assets/icons/Infrared/flash_text_21x5.png differ diff --git a/assets/icons/Infrared/heat_30x51.png b/assets/icons/Infrared/heat_30x51.png index aca27c7c8..f702816d6 100644 Binary files a/assets/icons/Infrared/heat_30x51.png and b/assets/icons/Infrared/heat_30x51.png differ diff --git a/assets/icons/Infrared/hourglass0_24x24.png b/assets/icons/Infrared/hourglass0_24x24.png index a382d84e2..ce627b002 100644 Binary files a/assets/icons/Infrared/hourglass0_24x24.png and b/assets/icons/Infrared/hourglass0_24x24.png differ diff --git a/assets/icons/Infrared/hourglass1_24x24.png b/assets/icons/Infrared/hourglass1_24x24.png index b4cc7b462..ef048a7bd 100644 Binary files a/assets/icons/Infrared/hourglass1_24x24.png and b/assets/icons/Infrared/hourglass1_24x24.png differ diff --git a/assets/icons/Infrared/hourglass2_24x24.png b/assets/icons/Infrared/hourglass2_24x24.png index d2c3709f7..918bd79d8 100644 Binary files a/assets/icons/Infrared/hourglass2_24x24.png and b/assets/icons/Infrared/hourglass2_24x24.png differ diff --git a/assets/icons/Infrared/hourglass3_24x24.png b/assets/icons/Infrared/hourglass3_24x24.png index e7be1e995..dccaf46cd 100644 Binary files a/assets/icons/Infrared/hourglass3_24x24.png and b/assets/icons/Infrared/hourglass3_24x24.png differ diff --git a/assets/icons/Infrared/hourglass4_24x24.png b/assets/icons/Infrared/hourglass4_24x24.png index 49eee2f53..7ed58a5b4 100644 Binary files a/assets/icons/Infrared/hourglass4_24x24.png and b/assets/icons/Infrared/hourglass4_24x24.png differ diff --git a/assets/icons/Infrared/hourglass5_24x24.png b/assets/icons/Infrared/hourglass5_24x24.png index 90e1d4b4e..f3a3ed308 100644 Binary files a/assets/icons/Infrared/hourglass5_24x24.png and b/assets/icons/Infrared/hourglass5_24x24.png differ diff --git a/assets/icons/Infrared/hourglass6_24x24.png b/assets/icons/Infrared/hourglass6_24x24.png index e68c744f0..1383bbbb9 100644 Binary files a/assets/icons/Infrared/hourglass6_24x24.png and b/assets/icons/Infrared/hourglass6_24x24.png differ diff --git a/assets/icons/Infrared/input_19x20.png b/assets/icons/Infrared/input_19x20.png index 37d0b2161..c1650b7bb 100644 Binary files a/assets/icons/Infrared/input_19x20.png and b/assets/icons/Infrared/input_19x20.png differ diff --git a/assets/icons/Infrared/input_hover_19x20.png b/assets/icons/Infrared/input_hover_19x20.png index fd3a50312..c6e28cb2e 100644 Binary files a/assets/icons/Infrared/input_hover_19x20.png and b/assets/icons/Infrared/input_hover_19x20.png differ diff --git a/assets/icons/Infrared/input_text_24x5.png b/assets/icons/Infrared/input_text_24x5.png index 77e90bb95..139b5539a 100644 Binary files a/assets/icons/Infrared/input_text_24x5.png and b/assets/icons/Infrared/input_text_24x5.png differ diff --git a/assets/icons/Infrared/max_24x23.png b/assets/icons/Infrared/max_24x23.png index d4163a65f..b7836abbf 100644 Binary files a/assets/icons/Infrared/max_24x23.png and b/assets/icons/Infrared/max_24x23.png differ diff --git a/assets/icons/Infrared/max_hover_24x23.png b/assets/icons/Infrared/max_hover_24x23.png index 65f97b0ce..f3e87a581 100644 Binary files a/assets/icons/Infrared/max_hover_24x23.png and b/assets/icons/Infrared/max_hover_24x23.png differ diff --git a/assets/icons/Infrared/menu_text_20x5.png b/assets/icons/Infrared/menu_text_20x5.png index 765278517..69ed3a78b 100644 Binary files a/assets/icons/Infrared/menu_text_20x5.png and b/assets/icons/Infrared/menu_text_20x5.png differ diff --git a/assets/icons/Infrared/mode_19x20.png b/assets/icons/Infrared/mode_19x20.png index fa0a946b6..ac4fe9c1d 100644 Binary files a/assets/icons/Infrared/mode_19x20.png and b/assets/icons/Infrared/mode_19x20.png differ diff --git a/assets/icons/Infrared/mode_hover_19x20.png b/assets/icons/Infrared/mode_hover_19x20.png index 92ada65be..f151d3827 100644 Binary files a/assets/icons/Infrared/mode_hover_19x20.png and b/assets/icons/Infrared/mode_hover_19x20.png differ diff --git a/assets/icons/Infrared/mode_text_20x5.png b/assets/icons/Infrared/mode_text_20x5.png index 2c8457d6f..a9c6571ca 100644 Binary files a/assets/icons/Infrared/mode_text_20x5.png and b/assets/icons/Infrared/mode_text_20x5.png differ diff --git a/assets/icons/Infrared/mute_19x20.png b/assets/icons/Infrared/mute_19x20.png index 410e88ac2..d767e2f9c 100644 Binary files a/assets/icons/Infrared/mute_19x20.png and b/assets/icons/Infrared/mute_19x20.png differ diff --git a/assets/icons/Infrared/mute_hover_19x20.png b/assets/icons/Infrared/mute_hover_19x20.png index e9a5b3510..cf899b883 100644 Binary files a/assets/icons/Infrared/mute_hover_19x20.png and b/assets/icons/Infrared/mute_hover_19x20.png differ diff --git a/assets/icons/Infrared/mute_text_19x5.png b/assets/icons/Infrared/mute_text_19x5.png index fa2d042a6..62183e5ac 100644 Binary files a/assets/icons/Infrared/mute_text_19x5.png and b/assets/icons/Infrared/mute_text_19x5.png differ diff --git a/assets/icons/Infrared/next_19x20.png b/assets/icons/Infrared/next_19x20.png index 512b68745..6d48639b8 100644 Binary files a/assets/icons/Infrared/next_19x20.png and b/assets/icons/Infrared/next_19x20.png differ diff --git a/assets/icons/Infrared/next_hover_19x20.png b/assets/icons/Infrared/next_hover_19x20.png index c84bfdb90..006b92a09 100644 Binary files a/assets/icons/Infrared/next_hover_19x20.png and b/assets/icons/Infrared/next_hover_19x20.png differ diff --git a/assets/icons/Infrared/next_text_19x6.png b/assets/icons/Infrared/next_text_19x6.png index 74d53171f..8146e688d 100644 Binary files a/assets/icons/Infrared/next_text_19x6.png and b/assets/icons/Infrared/next_text_19x6.png differ diff --git a/assets/icons/Infrared/off_19x20.png b/assets/icons/Infrared/off_19x20.png index 6d68d7e6e..8c97c072e 100644 Binary files a/assets/icons/Infrared/off_19x20.png and b/assets/icons/Infrared/off_19x20.png differ diff --git a/assets/icons/Infrared/off_hover_19x20.png b/assets/icons/Infrared/off_hover_19x20.png index fddd3f917..98c384838 100644 Binary files a/assets/icons/Infrared/off_hover_19x20.png and b/assets/icons/Infrared/off_hover_19x20.png differ diff --git a/assets/icons/Infrared/off_text_12x5.png b/assets/icons/Infrared/off_text_12x5.png index 500adbf27..7ee27fc7a 100644 Binary files a/assets/icons/Infrared/off_text_12x5.png and b/assets/icons/Infrared/off_text_12x5.png differ diff --git a/assets/icons/Infrared/pause_19x20.png b/assets/icons/Infrared/pause_19x20.png index 99196d23b..f3fda0fc4 100644 Binary files a/assets/icons/Infrared/pause_19x20.png and b/assets/icons/Infrared/pause_19x20.png differ diff --git a/assets/icons/Infrared/pause_hover_19x20.png b/assets/icons/Infrared/pause_hover_19x20.png index 33e7d8eb2..465c150a9 100644 Binary files a/assets/icons/Infrared/pause_hover_19x20.png and b/assets/icons/Infrared/pause_hover_19x20.png differ diff --git a/assets/icons/Infrared/pause_text_23x5.png b/assets/icons/Infrared/pause_text_23x5.png index 72c7b0403..fd991be3b 100644 Binary files a/assets/icons/Infrared/pause_text_23x5.png and b/assets/icons/Infrared/pause_text_23x5.png differ diff --git a/assets/icons/Infrared/play_19x20.png b/assets/icons/Infrared/play_19x20.png index 880e977d2..cb1d4ad80 100644 Binary files a/assets/icons/Infrared/play_19x20.png and b/assets/icons/Infrared/play_19x20.png differ diff --git a/assets/icons/Infrared/play_hover_19x20.png b/assets/icons/Infrared/play_hover_19x20.png index 4c837a144..35ab01448 100644 Binary files a/assets/icons/Infrared/play_hover_19x20.png and b/assets/icons/Infrared/play_hover_19x20.png differ diff --git a/assets/icons/Infrared/play_text_19x5.png b/assets/icons/Infrared/play_text_19x5.png index c5f067bcf..375f8155e 100644 Binary files a/assets/icons/Infrared/play_text_19x5.png and b/assets/icons/Infrared/play_text_19x5.png differ diff --git a/assets/icons/Infrared/power_19x20.png b/assets/icons/Infrared/power_19x20.png index 12b927973..eef764158 100644 Binary files a/assets/icons/Infrared/power_19x20.png and b/assets/icons/Infrared/power_19x20.png differ diff --git a/assets/icons/Infrared/power_hover_19x20.png b/assets/icons/Infrared/power_hover_19x20.png index 3a41249ff..c8e30cafa 100644 Binary files a/assets/icons/Infrared/power_hover_19x20.png and b/assets/icons/Infrared/power_hover_19x20.png differ diff --git a/assets/icons/Infrared/power_text_24x5.png b/assets/icons/Infrared/power_text_24x5.png index 88fff8e33..8f2fda83a 100644 Binary files a/assets/icons/Infrared/power_text_24x5.png and b/assets/icons/Infrared/power_text_24x5.png differ diff --git a/assets/icons/Infrared/prev_19x20.png b/assets/icons/Infrared/prev_19x20.png index 8d17cec57..69ac3bccb 100644 Binary files a/assets/icons/Infrared/prev_19x20.png and b/assets/icons/Infrared/prev_19x20.png differ diff --git a/assets/icons/Infrared/prev_hover_19x20.png b/assets/icons/Infrared/prev_hover_19x20.png index be9dce700..51f5779f0 100644 Binary files a/assets/icons/Infrared/prev_hover_19x20.png and b/assets/icons/Infrared/prev_hover_19x20.png differ diff --git a/assets/icons/Infrared/prev_text_19x5.png b/assets/icons/Infrared/prev_text_19x5.png index 473b89745..115887bbe 100644 Binary files a/assets/icons/Infrared/prev_text_19x5.png and b/assets/icons/Infrared/prev_text_19x5.png differ diff --git a/assets/icons/Infrared/rotate_19x20.png b/assets/icons/Infrared/rotate_19x20.png index 21f36da52..02d9231a9 100644 Binary files a/assets/icons/Infrared/rotate_19x20.png and b/assets/icons/Infrared/rotate_19x20.png differ diff --git a/assets/icons/Infrared/rotate_hover_19x20.png b/assets/icons/Infrared/rotate_hover_19x20.png index 581e90987..89319b433 100644 Binary files a/assets/icons/Infrared/rotate_hover_19x20.png and b/assets/icons/Infrared/rotate_hover_19x20.png differ diff --git a/assets/icons/Infrared/rotate_text_24x5.png b/assets/icons/Infrared/rotate_text_24x5.png index 851eac339..2e1f4b953 100644 Binary files a/assets/icons/Infrared/rotate_text_24x5.png and b/assets/icons/Infrared/rotate_text_24x5.png differ diff --git a/assets/icons/Infrared/speed_text_30x30.png b/assets/icons/Infrared/speed_text_30x30.png index c09eb1ab7..72dc357ba 100644 Binary files a/assets/icons/Infrared/speed_text_30x30.png and b/assets/icons/Infrared/speed_text_30x30.png differ diff --git a/assets/icons/Infrared/stop_19x20.png b/assets/icons/Infrared/stop_19x20.png index 28fc962a7..0fd0fb551 100644 Binary files a/assets/icons/Infrared/stop_19x20.png and b/assets/icons/Infrared/stop_19x20.png differ diff --git a/assets/icons/Infrared/stop_hover_19x20.png b/assets/icons/Infrared/stop_hover_19x20.png index 60935caf7..96986665a 100644 Binary files a/assets/icons/Infrared/stop_hover_19x20.png and b/assets/icons/Infrared/stop_hover_19x20.png differ diff --git a/assets/icons/Infrared/stop_text_19x5.png b/assets/icons/Infrared/stop_text_19x5.png index 2aea41ca1..9cc69315d 100644 Binary files a/assets/icons/Infrared/stop_text_19x5.png and b/assets/icons/Infrared/stop_text_19x5.png differ diff --git a/assets/icons/Infrared/timer_19x20.png b/assets/icons/Infrared/timer_19x20.png index 6c2bdf6bb..e5e20b6c1 100644 Binary files a/assets/icons/Infrared/timer_19x20.png and b/assets/icons/Infrared/timer_19x20.png differ diff --git a/assets/icons/Infrared/timer_hover_19x20.png b/assets/icons/Infrared/timer_hover_19x20.png index 560ef895d..5d34e5894 100644 Binary files a/assets/icons/Infrared/timer_hover_19x20.png and b/assets/icons/Infrared/timer_hover_19x20.png differ diff --git a/assets/icons/Infrared/timer_text_23x5.png b/assets/icons/Infrared/timer_text_23x5.png index ad2229f73..09a71c158 100644 Binary files a/assets/icons/Infrared/timer_text_23x5.png and b/assets/icons/Infrared/timer_text_23x5.png differ diff --git a/assets/icons/Infrared/vol_ac_text_30x30.png b/assets/icons/Infrared/vol_ac_text_30x30.png index 068266d62..2286627c8 100644 Binary files a/assets/icons/Infrared/vol_ac_text_30x30.png and b/assets/icons/Infrared/vol_ac_text_30x30.png differ diff --git a/assets/icons/Infrared/vol_tv_text_29x34.png b/assets/icons/Infrared/vol_tv_text_29x34.png index caef54c25..166cbdce6 100644 Binary files a/assets/icons/Infrared/vol_tv_text_29x34.png and b/assets/icons/Infrared/vol_tv_text_29x34.png differ diff --git a/assets/icons/Infrared/voldown_24x21.png b/assets/icons/Infrared/voldown_24x21.png index a80c59594..d6f8d2f32 100644 Binary files a/assets/icons/Infrared/voldown_24x21.png and b/assets/icons/Infrared/voldown_24x21.png differ diff --git a/assets/icons/Infrared/voldown_hover_24x21.png b/assets/icons/Infrared/voldown_hover_24x21.png index 6bc57c70e..b9ac48b4e 100644 Binary files a/assets/icons/Infrared/voldown_hover_24x21.png and b/assets/icons/Infrared/voldown_hover_24x21.png differ diff --git a/assets/icons/Infrared/volup_24x21.png b/assets/icons/Infrared/volup_24x21.png index 688552751..ebc3f3e42 100644 Binary files a/assets/icons/Infrared/volup_24x21.png and b/assets/icons/Infrared/volup_24x21.png differ diff --git a/assets/icons/Infrared/volup_hover_24x21.png b/assets/icons/Infrared/volup_hover_24x21.png index 5d790e796..1d35173d1 100644 Binary files a/assets/icons/Infrared/volup_hover_24x21.png and b/assets/icons/Infrared/volup_hover_24x21.png differ diff --git a/assets/icons/Interface/Lockscreen.png b/assets/icons/Interface/Lockscreen.png index ab4f0a739..518fef1e2 100644 Binary files a/assets/icons/Interface/Lockscreen.png and b/assets/icons/Interface/Lockscreen.png differ diff --git a/assets/icons/Interface/SmallArrowDown_3x5.png b/assets/icons/Interface/SmallArrowDown_3x5.png index 1912e5d24..e795d6708 100644 Binary files a/assets/icons/Interface/SmallArrowDown_3x5.png and b/assets/icons/Interface/SmallArrowDown_3x5.png differ diff --git a/assets/icons/Interface/SmallArrowUp_3x5.png b/assets/icons/Interface/SmallArrowUp_3x5.png index 9c6242078..4a4dc8a77 100644 Binary files a/assets/icons/Interface/SmallArrowUp_3x5.png and b/assets/icons/Interface/SmallArrowUp_3x5.png differ diff --git a/assets/icons/Keyboard/KeyBackspaceSelected_17x11.png b/assets/icons/Keyboard/KeyBackspaceSelected_17x11.png index 5255f78ce..1bdeb608a 100644 Binary files a/assets/icons/Keyboard/KeyBackspaceSelected_17x11.png and b/assets/icons/Keyboard/KeyBackspaceSelected_17x11.png differ diff --git a/assets/icons/Keyboard/KeyBackspace_17x11.png b/assets/icons/Keyboard/KeyBackspace_17x11.png index b78e81ea6..50f33bf16 100644 Binary files a/assets/icons/Keyboard/KeyBackspace_17x11.png and b/assets/icons/Keyboard/KeyBackspace_17x11.png differ diff --git a/assets/icons/Keyboard/KeyKeyboardSelected_10x11.png b/assets/icons/Keyboard/KeyKeyboardSelected_10x11.png index 231880386..22d2265aa 100644 Binary files a/assets/icons/Keyboard/KeyKeyboardSelected_10x11.png and b/assets/icons/Keyboard/KeyKeyboardSelected_10x11.png differ diff --git a/assets/icons/Keyboard/KeyKeyboard_10x11.png b/assets/icons/Keyboard/KeyKeyboard_10x11.png index 1f4c03478..08cb14bd4 100644 Binary files a/assets/icons/Keyboard/KeyKeyboard_10x11.png and b/assets/icons/Keyboard/KeyKeyboard_10x11.png differ diff --git a/assets/icons/Keyboard/KeySaveBlockedSelected_22x11.png b/assets/icons/Keyboard/KeySaveBlockedSelected_22x11.png new file mode 100644 index 000000000..459816646 Binary files /dev/null and b/assets/icons/Keyboard/KeySaveBlockedSelected_22x11.png differ diff --git a/assets/icons/Keyboard/KeySaveBlocked_22x11.png b/assets/icons/Keyboard/KeySaveBlocked_22x11.png new file mode 100644 index 000000000..59558c3ee Binary files /dev/null and b/assets/icons/Keyboard/KeySaveBlocked_22x11.png differ diff --git a/assets/icons/Keyboard/KeySaveSelected_22x11.png b/assets/icons/Keyboard/KeySaveSelected_22x11.png index ba911105a..6620d51c1 100644 Binary files a/assets/icons/Keyboard/KeySaveSelected_22x11.png and b/assets/icons/Keyboard/KeySaveSelected_22x11.png differ diff --git a/assets/icons/Keyboard/KeySave_22x11.png b/assets/icons/Keyboard/KeySave_22x11.png index 46fd148e5..c67939023 100644 Binary files a/assets/icons/Keyboard/KeySave_22x11.png and b/assets/icons/Keyboard/KeySave_22x11.png differ diff --git a/assets/icons/Keyboard/KeySignSelected_21x11.png b/assets/icons/Keyboard/KeySignSelected_21x11.png new file mode 100644 index 000000000..23ec2a9c4 Binary files /dev/null and b/assets/icons/Keyboard/KeySignSelected_21x11.png differ diff --git a/assets/icons/Keyboard/KeySign_21x11.png b/assets/icons/Keyboard/KeySign_21x11.png new file mode 100644 index 000000000..f31e9e0fa Binary files /dev/null and b/assets/icons/Keyboard/KeySign_21x11.png differ diff --git a/assets/icons/Loader/err_01.png b/assets/icons/Loader/err_01.png index 7ffdf761d..f8a43d892 100644 Binary files a/assets/icons/Loader/err_01.png and b/assets/icons/Loader/err_01.png differ diff --git a/assets/icons/Loader/err_02.png b/assets/icons/Loader/err_02.png index e00b1cb3b..94fab160f 100644 Binary files a/assets/icons/Loader/err_02.png and b/assets/icons/Loader/err_02.png differ diff --git a/assets/icons/Loader/err_03.png b/assets/icons/Loader/err_03.png index bb28c29ab..83b12af0a 100644 Binary files a/assets/icons/Loader/err_03.png and b/assets/icons/Loader/err_03.png differ diff --git a/assets/icons/Loader/err_04.png b/assets/icons/Loader/err_04.png index 40d9f9b9e..503652196 100644 Binary files a/assets/icons/Loader/err_04.png and b/assets/icons/Loader/err_04.png differ diff --git a/assets/icons/Loader/err_05.png b/assets/icons/Loader/err_05.png index c606f9a33..b639ba5d8 100644 Binary files a/assets/icons/Loader/err_05.png and b/assets/icons/Loader/err_05.png differ diff --git a/assets/icons/Loader/err_06.png b/assets/icons/Loader/err_06.png index f8c4f11ba..8220848d6 100644 Binary files a/assets/icons/Loader/err_06.png and b/assets/icons/Loader/err_06.png differ diff --git a/assets/icons/Loader/err_07.png b/assets/icons/Loader/err_07.png index 1eb6fdd58..dc20b4da2 100644 Binary files a/assets/icons/Loader/err_07.png and b/assets/icons/Loader/err_07.png differ diff --git a/assets/icons/Loader/err_09.png b/assets/icons/Loader/err_09.png index 5f3b4e579..7378aff72 100644 Binary files a/assets/icons/Loader/err_09.png and b/assets/icons/Loader/err_09.png differ diff --git a/assets/icons/MainMenu/125khz_14/frame_01.png b/assets/icons/MainMenu/125khz_14/frame_01.png index 0f46d4262..d00392a1b 100644 Binary files a/assets/icons/MainMenu/125khz_14/frame_01.png and b/assets/icons/MainMenu/125khz_14/frame_01.png differ diff --git a/assets/icons/MainMenu/125khz_14/frame_02.png b/assets/icons/MainMenu/125khz_14/frame_02.png index 13c252b14..6ffd7fe16 100644 Binary files a/assets/icons/MainMenu/125khz_14/frame_02.png and b/assets/icons/MainMenu/125khz_14/frame_02.png differ diff --git a/assets/icons/MainMenu/125khz_14/frame_03.png b/assets/icons/MainMenu/125khz_14/frame_03.png index cdc882e7e..afd20d347 100644 Binary files a/assets/icons/MainMenu/125khz_14/frame_03.png and b/assets/icons/MainMenu/125khz_14/frame_03.png differ diff --git a/assets/icons/MainMenu/125khz_14/frame_04.png b/assets/icons/MainMenu/125khz_14/frame_04.png index bdbc7adf5..cf93c63f8 100644 Binary files a/assets/icons/MainMenu/125khz_14/frame_04.png and b/assets/icons/MainMenu/125khz_14/frame_04.png differ diff --git a/assets/icons/MainMenu/BadKb_14/frame_01.png b/assets/icons/MainMenu/BadKb_14/frame_01.png index 162753d8a..b2fb1d653 100644 Binary files a/assets/icons/MainMenu/BadKb_14/frame_01.png and b/assets/icons/MainMenu/BadKb_14/frame_01.png differ diff --git a/assets/icons/MainMenu/BadKb_14/frame_02.png b/assets/icons/MainMenu/BadKb_14/frame_02.png index 50e12f8ba..4060dc72f 100644 Binary files a/assets/icons/MainMenu/BadKb_14/frame_02.png and b/assets/icons/MainMenu/BadKb_14/frame_02.png differ diff --git a/assets/icons/MainMenu/BadKb_14/frame_03.png b/assets/icons/MainMenu/BadKb_14/frame_03.png index 5dafb2597..6b720f8a9 100644 Binary files a/assets/icons/MainMenu/BadKb_14/frame_03.png and b/assets/icons/MainMenu/BadKb_14/frame_03.png differ diff --git a/assets/icons/MainMenu/BadKb_14/frame_04.png b/assets/icons/MainMenu/BadKb_14/frame_04.png index 6ca08f842..f1931ef5e 100644 Binary files a/assets/icons/MainMenu/BadKb_14/frame_04.png and b/assets/icons/MainMenu/BadKb_14/frame_04.png differ diff --git a/assets/icons/MainMenu/BadKb_14/frame_05.png b/assets/icons/MainMenu/BadKb_14/frame_05.png index a3b06a0e7..8e32911da 100644 Binary files a/assets/icons/MainMenu/BadKb_14/frame_05.png and b/assets/icons/MainMenu/BadKb_14/frame_05.png differ diff --git a/assets/icons/MainMenu/BadKb_14/frame_06.png b/assets/icons/MainMenu/BadKb_14/frame_06.png index 7d8f43653..47e0a7a39 100644 Binary files a/assets/icons/MainMenu/BadKb_14/frame_06.png and b/assets/icons/MainMenu/BadKb_14/frame_06.png differ diff --git a/assets/icons/MainMenu/BadKb_14/frame_07.png b/assets/icons/MainMenu/BadKb_14/frame_07.png index a3b06a0e7..8e32911da 100644 Binary files a/assets/icons/MainMenu/BadKb_14/frame_07.png and b/assets/icons/MainMenu/BadKb_14/frame_07.png differ diff --git a/assets/icons/MainMenu/BadKb_14/frame_08.png b/assets/icons/MainMenu/BadKb_14/frame_08.png index 6ca08f842..f1931ef5e 100644 Binary files a/assets/icons/MainMenu/BadKb_14/frame_08.png and b/assets/icons/MainMenu/BadKb_14/frame_08.png differ diff --git a/assets/icons/MainMenu/BadKb_14/frame_09.png b/assets/icons/MainMenu/BadKb_14/frame_09.png index 5dafb2597..6b720f8a9 100644 Binary files a/assets/icons/MainMenu/BadKb_14/frame_09.png and b/assets/icons/MainMenu/BadKb_14/frame_09.png differ diff --git a/assets/icons/MainMenu/BadKb_14/frame_10.png b/assets/icons/MainMenu/BadKb_14/frame_10.png index 50e12f8ba..4060dc72f 100644 Binary files a/assets/icons/MainMenu/BadKb_14/frame_10.png and b/assets/icons/MainMenu/BadKb_14/frame_10.png differ diff --git a/assets/icons/MainMenu/BadKb_14/frame_11.png b/assets/icons/MainMenu/BadKb_14/frame_11.png index 162753d8a..b2fb1d653 100644 Binary files a/assets/icons/MainMenu/BadKb_14/frame_11.png and b/assets/icons/MainMenu/BadKb_14/frame_11.png differ diff --git a/assets/icons/MainMenu/GPIO_14/frame_01.png b/assets/icons/MainMenu/GPIO_14/frame_01.png index 23e27d59c..97c2ccaf2 100644 Binary files a/assets/icons/MainMenu/GPIO_14/frame_01.png and b/assets/icons/MainMenu/GPIO_14/frame_01.png differ diff --git a/assets/icons/MainMenu/GPIO_14/frame_02.png b/assets/icons/MainMenu/GPIO_14/frame_02.png index aa171cfaf..7e227af42 100644 Binary files a/assets/icons/MainMenu/GPIO_14/frame_02.png and b/assets/icons/MainMenu/GPIO_14/frame_02.png differ diff --git a/assets/icons/MainMenu/GPIO_14/frame_03.png b/assets/icons/MainMenu/GPIO_14/frame_03.png index 42fef0327..e2d7a420e 100644 Binary files a/assets/icons/MainMenu/GPIO_14/frame_03.png and b/assets/icons/MainMenu/GPIO_14/frame_03.png differ diff --git a/assets/icons/MainMenu/GPIO_14/frame_04.png b/assets/icons/MainMenu/GPIO_14/frame_04.png index 52ac41fb8..e801c88f5 100644 Binary files a/assets/icons/MainMenu/GPIO_14/frame_04.png and b/assets/icons/MainMenu/GPIO_14/frame_04.png differ diff --git a/assets/icons/MainMenu/GPIO_14/frame_05.png b/assets/icons/MainMenu/GPIO_14/frame_05.png index 30a259371..ebdc1382a 100644 Binary files a/assets/icons/MainMenu/GPIO_14/frame_05.png and b/assets/icons/MainMenu/GPIO_14/frame_05.png differ diff --git a/assets/icons/MainMenu/GPIO_14/frame_06.png b/assets/icons/MainMenu/GPIO_14/frame_06.png index be19567f3..5ebb0953f 100644 Binary files a/assets/icons/MainMenu/GPIO_14/frame_06.png and b/assets/icons/MainMenu/GPIO_14/frame_06.png differ diff --git a/assets/icons/MainMenu/GPIO_14/frame_07.png b/assets/icons/MainMenu/GPIO_14/frame_07.png index 2f7a42368..7138b727d 100644 Binary files a/assets/icons/MainMenu/GPIO_14/frame_07.png and b/assets/icons/MainMenu/GPIO_14/frame_07.png differ diff --git a/assets/icons/MainMenu/GPIO_14/frame_08.png b/assets/icons/MainMenu/GPIO_14/frame_08.png index aa4ad384d..a753127a8 100644 Binary files a/assets/icons/MainMenu/GPIO_14/frame_08.png and b/assets/icons/MainMenu/GPIO_14/frame_08.png differ diff --git a/assets/icons/MainMenu/Infrared_14/frame_01.png b/assets/icons/MainMenu/Infrared_14/frame_01.png index 63256dfff..b9ea5b6f9 100644 Binary files a/assets/icons/MainMenu/Infrared_14/frame_01.png and b/assets/icons/MainMenu/Infrared_14/frame_01.png differ diff --git a/assets/icons/MainMenu/Infrared_14/frame_02.png b/assets/icons/MainMenu/Infrared_14/frame_02.png index b31366d60..172c2eba7 100644 Binary files a/assets/icons/MainMenu/Infrared_14/frame_02.png and b/assets/icons/MainMenu/Infrared_14/frame_02.png differ diff --git a/assets/icons/MainMenu/Infrared_14/frame_03.png b/assets/icons/MainMenu/Infrared_14/frame_03.png index aed6b807c..8b6667b5b 100644 Binary files a/assets/icons/MainMenu/Infrared_14/frame_03.png and b/assets/icons/MainMenu/Infrared_14/frame_03.png differ diff --git a/assets/icons/MainMenu/Infrared_14/frame_04.png b/assets/icons/MainMenu/Infrared_14/frame_04.png index df7829408..bf2e55641 100644 Binary files a/assets/icons/MainMenu/Infrared_14/frame_04.png and b/assets/icons/MainMenu/Infrared_14/frame_04.png differ diff --git a/assets/icons/MainMenu/Infrared_14/frame_05.png b/assets/icons/MainMenu/Infrared_14/frame_05.png index bc1229a25..8a08e093c 100644 Binary files a/assets/icons/MainMenu/Infrared_14/frame_05.png and b/assets/icons/MainMenu/Infrared_14/frame_05.png differ diff --git a/assets/icons/MainMenu/Infrared_14/frame_06.png b/assets/icons/MainMenu/Infrared_14/frame_06.png index 711390213..50590d6bb 100644 Binary files a/assets/icons/MainMenu/Infrared_14/frame_06.png and b/assets/icons/MainMenu/Infrared_14/frame_06.png differ diff --git a/assets/icons/MainMenu/Momentum_14/frame_01.png b/assets/icons/MainMenu/Momentum_14/frame_01.png index 91973344f..74e1a065c 100644 Binary files a/assets/icons/MainMenu/Momentum_14/frame_01.png and b/assets/icons/MainMenu/Momentum_14/frame_01.png differ diff --git a/assets/icons/MainMenu/Momentum_14/frame_02.png b/assets/icons/MainMenu/Momentum_14/frame_02.png index 9044c637e..74e1a065c 100644 Binary files a/assets/icons/MainMenu/Momentum_14/frame_02.png and b/assets/icons/MainMenu/Momentum_14/frame_02.png differ diff --git a/assets/icons/MainMenu/Momentum_14/frame_03.png b/assets/icons/MainMenu/Momentum_14/frame_03.png index 9044c637e..74e1a065c 100644 Binary files a/assets/icons/MainMenu/Momentum_14/frame_03.png and b/assets/icons/MainMenu/Momentum_14/frame_03.png differ diff --git a/assets/icons/MainMenu/Momentum_14/frame_04.png b/assets/icons/MainMenu/Momentum_14/frame_04.png index 9044c637e..74e1a065c 100644 Binary files a/assets/icons/MainMenu/Momentum_14/frame_04.png and b/assets/icons/MainMenu/Momentum_14/frame_04.png differ diff --git a/assets/icons/MainMenu/Momentum_14/frame_05.png b/assets/icons/MainMenu/Momentum_14/frame_05.png index 6f5ff6860..ce01c02a6 100644 Binary files a/assets/icons/MainMenu/Momentum_14/frame_05.png and b/assets/icons/MainMenu/Momentum_14/frame_05.png differ diff --git a/assets/icons/MainMenu/Momentum_14/frame_06.png b/assets/icons/MainMenu/Momentum_14/frame_06.png index 9044c637e..74e1a065c 100644 Binary files a/assets/icons/MainMenu/Momentum_14/frame_06.png and b/assets/icons/MainMenu/Momentum_14/frame_06.png differ diff --git a/assets/icons/MainMenu/Momentum_14/frame_07.png b/assets/icons/MainMenu/Momentum_14/frame_07.png index 6f5ff6860..ce01c02a6 100644 Binary files a/assets/icons/MainMenu/Momentum_14/frame_07.png and b/assets/icons/MainMenu/Momentum_14/frame_07.png differ diff --git a/assets/icons/MainMenu/Momentum_14/frame_08.png b/assets/icons/MainMenu/Momentum_14/frame_08.png index 6f5ff6860..ce01c02a6 100644 Binary files a/assets/icons/MainMenu/Momentum_14/frame_08.png and b/assets/icons/MainMenu/Momentum_14/frame_08.png differ diff --git a/assets/icons/MainMenu/Momentum_14/frame_09.png b/assets/icons/MainMenu/Momentum_14/frame_09.png index 7b0b82c5a..26d169001 100644 Binary files a/assets/icons/MainMenu/Momentum_14/frame_09.png and b/assets/icons/MainMenu/Momentum_14/frame_09.png differ diff --git a/assets/icons/MainMenu/Momentum_14/frame_10.png b/assets/icons/MainMenu/Momentum_14/frame_10.png index ebcd408a6..50ad6f768 100644 Binary files a/assets/icons/MainMenu/Momentum_14/frame_10.png and b/assets/icons/MainMenu/Momentum_14/frame_10.png differ diff --git a/assets/icons/MainMenu/Momentum_14/frame_11.png b/assets/icons/MainMenu/Momentum_14/frame_11.png index 3a0377c7d..74e1a065c 100644 Binary files a/assets/icons/MainMenu/Momentum_14/frame_11.png and b/assets/icons/MainMenu/Momentum_14/frame_11.png differ diff --git a/assets/icons/MainMenu/NFC_14/frame_01.png b/assets/icons/MainMenu/NFC_14/frame_01.png index 84b79da13..e96d0293c 100644 Binary files a/assets/icons/MainMenu/NFC_14/frame_01.png and b/assets/icons/MainMenu/NFC_14/frame_01.png differ diff --git a/assets/icons/MainMenu/NFC_14/frame_02.png b/assets/icons/MainMenu/NFC_14/frame_02.png index d8da3d730..7ba638842 100644 Binary files a/assets/icons/MainMenu/NFC_14/frame_02.png and b/assets/icons/MainMenu/NFC_14/frame_02.png differ diff --git a/assets/icons/MainMenu/NFC_14/frame_03.png b/assets/icons/MainMenu/NFC_14/frame_03.png index d33251fbf..442dde8ca 100644 Binary files a/assets/icons/MainMenu/NFC_14/frame_03.png and b/assets/icons/MainMenu/NFC_14/frame_03.png differ diff --git a/assets/icons/MainMenu/NFC_14/frame_04.png b/assets/icons/MainMenu/NFC_14/frame_04.png index 568151d7d..6a0b8acb9 100644 Binary files a/assets/icons/MainMenu/NFC_14/frame_04.png and b/assets/icons/MainMenu/NFC_14/frame_04.png differ diff --git a/assets/icons/MainMenu/Plugins_14/frame_01.png b/assets/icons/MainMenu/Plugins_14/frame_01.png index a3e192b83..bc7cc779a 100644 Binary files a/assets/icons/MainMenu/Plugins_14/frame_01.png and b/assets/icons/MainMenu/Plugins_14/frame_01.png differ diff --git a/assets/icons/MainMenu/Plugins_14/frame_02.png b/assets/icons/MainMenu/Plugins_14/frame_02.png index f025f2309..c914a3e9f 100644 Binary files a/assets/icons/MainMenu/Plugins_14/frame_02.png and b/assets/icons/MainMenu/Plugins_14/frame_02.png differ diff --git a/assets/icons/MainMenu/Plugins_14/frame_03.png b/assets/icons/MainMenu/Plugins_14/frame_03.png index f82dd553a..47a1473ff 100644 Binary files a/assets/icons/MainMenu/Plugins_14/frame_03.png and b/assets/icons/MainMenu/Plugins_14/frame_03.png differ diff --git a/assets/icons/MainMenu/Plugins_14/frame_04.png b/assets/icons/MainMenu/Plugins_14/frame_04.png index bc22d3b00..0230d16a7 100644 Binary files a/assets/icons/MainMenu/Plugins_14/frame_04.png and b/assets/icons/MainMenu/Plugins_14/frame_04.png differ diff --git a/assets/icons/MainMenu/Plugins_14/frame_05.png b/assets/icons/MainMenu/Plugins_14/frame_05.png index ddbe5f700..951816148 100644 Binary files a/assets/icons/MainMenu/Plugins_14/frame_05.png and b/assets/icons/MainMenu/Plugins_14/frame_05.png differ diff --git a/assets/icons/MainMenu/Plugins_14/frame_06.png b/assets/icons/MainMenu/Plugins_14/frame_06.png index 3ce0f8aca..affe37cfa 100644 Binary files a/assets/icons/MainMenu/Plugins_14/frame_06.png and b/assets/icons/MainMenu/Plugins_14/frame_06.png differ diff --git a/assets/icons/MainMenu/Plugins_14/frame_07.png b/assets/icons/MainMenu/Plugins_14/frame_07.png index 91a1125de..0ccf3f271 100644 Binary files a/assets/icons/MainMenu/Plugins_14/frame_07.png and b/assets/icons/MainMenu/Plugins_14/frame_07.png differ diff --git a/assets/icons/MainMenu/Plugins_14/frame_08.png b/assets/icons/MainMenu/Plugins_14/frame_08.png index c302db0ab..360cae32c 100644 Binary files a/assets/icons/MainMenu/Plugins_14/frame_08.png and b/assets/icons/MainMenu/Plugins_14/frame_08.png differ diff --git a/assets/icons/MainMenu/Plugins_14/frame_09.png b/assets/icons/MainMenu/Plugins_14/frame_09.png index 2be305721..15c2e0a8e 100644 Binary files a/assets/icons/MainMenu/Plugins_14/frame_09.png and b/assets/icons/MainMenu/Plugins_14/frame_09.png differ diff --git a/assets/icons/MainMenu/Settings_14/frame_01.png b/assets/icons/MainMenu/Settings_14/frame_01.png index aad9e3558..1f8f45ee1 100644 Binary files a/assets/icons/MainMenu/Settings_14/frame_01.png and b/assets/icons/MainMenu/Settings_14/frame_01.png differ diff --git a/assets/icons/MainMenu/Settings_14/frame_02.png b/assets/icons/MainMenu/Settings_14/frame_02.png index 124ffde21..8127986f3 100644 Binary files a/assets/icons/MainMenu/Settings_14/frame_02.png and b/assets/icons/MainMenu/Settings_14/frame_02.png differ diff --git a/assets/icons/MainMenu/Settings_14/frame_03.png b/assets/icons/MainMenu/Settings_14/frame_03.png index e4d72fe6f..0479bef21 100644 Binary files a/assets/icons/MainMenu/Settings_14/frame_03.png and b/assets/icons/MainMenu/Settings_14/frame_03.png differ diff --git a/assets/icons/MainMenu/Settings_14/frame_04.png b/assets/icons/MainMenu/Settings_14/frame_04.png index fec89bb85..192df5fdb 100644 Binary files a/assets/icons/MainMenu/Settings_14/frame_04.png and b/assets/icons/MainMenu/Settings_14/frame_04.png differ diff --git a/assets/icons/MainMenu/Settings_14/frame_05.png b/assets/icons/MainMenu/Settings_14/frame_05.png index fadaebc9f..5aaa83010 100644 Binary files a/assets/icons/MainMenu/Settings_14/frame_05.png and b/assets/icons/MainMenu/Settings_14/frame_05.png differ diff --git a/assets/icons/MainMenu/Settings_14/frame_06.png b/assets/icons/MainMenu/Settings_14/frame_06.png index 5b7b6423b..89082d7e2 100644 Binary files a/assets/icons/MainMenu/Settings_14/frame_06.png and b/assets/icons/MainMenu/Settings_14/frame_06.png differ diff --git a/assets/icons/MainMenu/Settings_14/frame_07.png b/assets/icons/MainMenu/Settings_14/frame_07.png index 6301512e8..424e68a08 100644 Binary files a/assets/icons/MainMenu/Settings_14/frame_07.png and b/assets/icons/MainMenu/Settings_14/frame_07.png differ diff --git a/assets/icons/MainMenu/Settings_14/frame_08.png b/assets/icons/MainMenu/Settings_14/frame_08.png index ce0611e34..347b760e9 100644 Binary files a/assets/icons/MainMenu/Settings_14/frame_08.png and b/assets/icons/MainMenu/Settings_14/frame_08.png differ diff --git a/assets/icons/MainMenu/Settings_14/frame_09.png b/assets/icons/MainMenu/Settings_14/frame_09.png index 11e93da37..64794e7ee 100644 Binary files a/assets/icons/MainMenu/Settings_14/frame_09.png and b/assets/icons/MainMenu/Settings_14/frame_09.png differ diff --git a/assets/icons/MainMenu/Settings_14/frame_10.png b/assets/icons/MainMenu/Settings_14/frame_10.png index aad9e3558..1f8f45ee1 100644 Binary files a/assets/icons/MainMenu/Settings_14/frame_10.png and b/assets/icons/MainMenu/Settings_14/frame_10.png differ diff --git a/assets/icons/MainMenu/Sub1ghz_14/frame_01.png b/assets/icons/MainMenu/Sub1ghz_14/frame_01.png index 52dc4ad21..ba1b89f9f 100644 Binary files a/assets/icons/MainMenu/Sub1ghz_14/frame_01.png and b/assets/icons/MainMenu/Sub1ghz_14/frame_01.png differ diff --git a/assets/icons/MainMenu/Sub1ghz_14/frame_02.png b/assets/icons/MainMenu/Sub1ghz_14/frame_02.png index 2dff1c031..c34b691bc 100644 Binary files a/assets/icons/MainMenu/Sub1ghz_14/frame_02.png and b/assets/icons/MainMenu/Sub1ghz_14/frame_02.png differ diff --git a/assets/icons/MainMenu/Sub1ghz_14/frame_03.png b/assets/icons/MainMenu/Sub1ghz_14/frame_03.png index c1e438b01..420e568ce 100644 Binary files a/assets/icons/MainMenu/Sub1ghz_14/frame_03.png and b/assets/icons/MainMenu/Sub1ghz_14/frame_03.png differ diff --git a/assets/icons/MainMenu/Sub1ghz_14/frame_04.png b/assets/icons/MainMenu/Sub1ghz_14/frame_04.png index 169fb6147..c40eee7b2 100644 Binary files a/assets/icons/MainMenu/Sub1ghz_14/frame_04.png and b/assets/icons/MainMenu/Sub1ghz_14/frame_04.png differ diff --git a/assets/icons/MainMenu/Sub1ghz_14/frame_05.png b/assets/icons/MainMenu/Sub1ghz_14/frame_05.png index 79b2bc972..08a6a6194 100644 Binary files a/assets/icons/MainMenu/Sub1ghz_14/frame_05.png and b/assets/icons/MainMenu/Sub1ghz_14/frame_05.png differ diff --git a/assets/icons/MainMenu/Sub1ghz_14/frame_06.png b/assets/icons/MainMenu/Sub1ghz_14/frame_06.png index 8fce0c44d..291fa8ace 100644 Binary files a/assets/icons/MainMenu/Sub1ghz_14/frame_06.png and b/assets/icons/MainMenu/Sub1ghz_14/frame_06.png differ diff --git a/assets/icons/MainMenu/U2F_14/frame_01.png b/assets/icons/MainMenu/U2F_14/frame_01.png index 6903a28b8..0dc3edfab 100644 Binary files a/assets/icons/MainMenu/U2F_14/frame_01.png and b/assets/icons/MainMenu/U2F_14/frame_01.png differ diff --git a/assets/icons/MainMenu/U2F_14/frame_02.png b/assets/icons/MainMenu/U2F_14/frame_02.png index e4bba739d..21dc5fa7d 100644 Binary files a/assets/icons/MainMenu/U2F_14/frame_02.png and b/assets/icons/MainMenu/U2F_14/frame_02.png differ diff --git a/assets/icons/MainMenu/U2F_14/frame_03.png b/assets/icons/MainMenu/U2F_14/frame_03.png index 4c903182c..d516bf7f6 100644 Binary files a/assets/icons/MainMenu/U2F_14/frame_03.png and b/assets/icons/MainMenu/U2F_14/frame_03.png differ diff --git a/assets/icons/MainMenu/U2F_14/frame_04.png b/assets/icons/MainMenu/U2F_14/frame_04.png index e4bba739d..21dc5fa7d 100644 Binary files a/assets/icons/MainMenu/U2F_14/frame_04.png and b/assets/icons/MainMenu/U2F_14/frame_04.png differ diff --git a/assets/icons/MainMenu/iButton_14/frame_01.png b/assets/icons/MainMenu/iButton_14/frame_01.png index d9f10748e..6e7398d86 100644 Binary files a/assets/icons/MainMenu/iButton_14/frame_01.png and b/assets/icons/MainMenu/iButton_14/frame_01.png differ diff --git a/assets/icons/MainMenu/iButton_14/frame_02.png b/assets/icons/MainMenu/iButton_14/frame_02.png index cf3422c03..531364566 100644 Binary files a/assets/icons/MainMenu/iButton_14/frame_02.png and b/assets/icons/MainMenu/iButton_14/frame_02.png differ diff --git a/assets/icons/MainMenu/iButton_14/frame_03.png b/assets/icons/MainMenu/iButton_14/frame_03.png index 1b0ed62e0..31354eeff 100644 Binary files a/assets/icons/MainMenu/iButton_14/frame_03.png and b/assets/icons/MainMenu/iButton_14/frame_03.png differ diff --git a/assets/icons/MainMenu/iButton_14/frame_04.png b/assets/icons/MainMenu/iButton_14/frame_04.png index 0caa9956b..78bc56178 100644 Binary files a/assets/icons/MainMenu/iButton_14/frame_04.png and b/assets/icons/MainMenu/iButton_14/frame_04.png differ diff --git a/assets/icons/MainMenu/iButton_14/frame_05.png b/assets/icons/MainMenu/iButton_14/frame_05.png index 79f217b96..82dbaedeb 100644 Binary files a/assets/icons/MainMenu/iButton_14/frame_05.png and b/assets/icons/MainMenu/iButton_14/frame_05.png differ diff --git a/assets/icons/MainMenu/iButton_14/frame_06.png b/assets/icons/MainMenu/iButton_14/frame_06.png index eabb2b190..5d7163d54 100644 Binary files a/assets/icons/MainMenu/iButton_14/frame_06.png and b/assets/icons/MainMenu/iButton_14/frame_06.png differ diff --git a/assets/icons/MainMenu/iButton_14/frame_07.png b/assets/icons/MainMenu/iButton_14/frame_07.png index 3a30aa7fb..3020c8105 100644 Binary files a/assets/icons/MainMenu/iButton_14/frame_07.png and b/assets/icons/MainMenu/iButton_14/frame_07.png differ diff --git a/assets/icons/NFC/ArrowC_1_36x36.png b/assets/icons/NFC/ArrowC_1_36x36.png index 3a0c6dd0c..0f4d3e1b2 100644 Binary files a/assets/icons/NFC/ArrowC_1_36x36.png and b/assets/icons/NFC/ArrowC_1_36x36.png differ diff --git a/assets/icons/NFC/Keychain_39x36.png b/assets/icons/NFC/Keychain_39x36.png index d15850b5b..773f388d5 100644 Binary files a/assets/icons/NFC/Keychain_39x36.png and b/assets/icons/NFC/Keychain_39x36.png differ diff --git a/assets/icons/NFC/MFKey_qr_25x25.png b/assets/icons/NFC/MFKey_qr_25x25.png index feb07e280..7059260ea 100644 Binary files a/assets/icons/NFC/MFKey_qr_25x25.png and b/assets/icons/NFC/MFKey_qr_25x25.png differ diff --git a/assets/icons/NFC/Modern_reader_18x34.png b/assets/icons/NFC/Modern_reader_18x34.png index b19c0f30c..aac13396a 100644 Binary files a/assets/icons/NFC/Modern_reader_18x34.png and b/assets/icons/NFC/Modern_reader_18x34.png differ diff --git a/assets/icons/NFC/Move_flipper_26x39.png b/assets/icons/NFC/Move_flipper_26x39.png index ff4af9ff0..981c17236 100644 Binary files a/assets/icons/NFC/Move_flipper_26x39.png and b/assets/icons/NFC/Move_flipper_26x39.png differ diff --git a/assets/icons/NFC/NFC_dolphin_emulation_51x64.png b/assets/icons/NFC/NFC_dolphin_emulation_51x64.png index ad5646d16..ef57f73c4 100644 Binary files a/assets/icons/NFC/NFC_dolphin_emulation_51x64.png and b/assets/icons/NFC/NFC_dolphin_emulation_51x64.png differ diff --git a/assets/icons/NFC/NFC_manual_60x50.png b/assets/icons/NFC/NFC_manual_60x50.png index 787c0bcfe..6a7f75499 100644 Binary files a/assets/icons/NFC/NFC_manual_60x50.png and b/assets/icons/NFC/NFC_manual_60x50.png differ diff --git a/assets/icons/NFC/Release_arrow_18x15.png b/assets/icons/NFC/Release_arrow_18x15.png index 187a90345..bd487fdb5 100644 Binary files a/assets/icons/NFC/Release_arrow_18x15.png and b/assets/icons/NFC/Release_arrow_18x15.png differ diff --git a/assets/icons/NFC/check_big_20x17.png b/assets/icons/NFC/check_big_20x17.png index 0e84cfa07..ddc7d3721 100644 Binary files a/assets/icons/NFC/check_big_20x17.png and b/assets/icons/NFC/check_big_20x17.png differ diff --git a/assets/icons/PIN/Pin_arrow_up_7x9.png b/assets/icons/PIN/Pin_arrow_up_7x9.png index a91a6fd5e..4e199c7d0 100644 Binary files a/assets/icons/PIN/Pin_arrow_up_7x9.png and b/assets/icons/PIN/Pin_arrow_up_7x9.png differ diff --git a/assets/icons/PIN/Pin_attention_dpad_29x29.png b/assets/icons/PIN/Pin_attention_dpad_29x29.png index 984db9cc7..65a2670a0 100644 Binary files a/assets/icons/PIN/Pin_attention_dpad_29x29.png and b/assets/icons/PIN/Pin_attention_dpad_29x29.png differ diff --git a/assets/icons/PIN/Pin_back_arrow_10x8.png b/assets/icons/PIN/Pin_back_arrow_10x8.png index 3bafabd14..64b25db5a 100644 Binary files a/assets/icons/PIN/Pin_back_arrow_10x8.png and b/assets/icons/PIN/Pin_back_arrow_10x8.png differ diff --git a/assets/icons/PIN/Pin_cell_13x13.png b/assets/icons/PIN/Pin_cell_13x13.png index 1b1ff0c2f..5362df841 100644 Binary files a/assets/icons/PIN/Pin_cell_13x13.png and b/assets/icons/PIN/Pin_cell_13x13.png differ diff --git a/assets/icons/PIN/Pin_pointer_5x3.png b/assets/icons/PIN/Pin_pointer_5x3.png index edf3d41bb..4a4dc8a77 100644 Binary files a/assets/icons/PIN/Pin_pointer_5x3.png and b/assets/icons/PIN/Pin_pointer_5x3.png differ diff --git a/assets/icons/PIN/Pin_star_7x7.png b/assets/icons/PIN/Pin_star_7x7.png index 42fdea86e..3ab57222d 100644 Binary files a/assets/icons/PIN/Pin_star_7x7.png and b/assets/icons/PIN/Pin_star_7x7.png differ diff --git a/assets/icons/Passport/passport_128x64.png b/assets/icons/Passport/passport_128x64.png index ba911073c..0c5d14daf 100644 Binary files a/assets/icons/Passport/passport_128x64.png and b/assets/icons/Passport/passport_128x64.png differ diff --git a/assets/icons/Passport/passport_bad_46x49.png b/assets/icons/Passport/passport_bad_46x49.png index d11682ab8..890941257 100644 Binary files a/assets/icons/Passport/passport_bad_46x49.png and b/assets/icons/Passport/passport_bad_46x49.png differ diff --git a/assets/icons/Passport/passport_happy_46x49.png b/assets/icons/Passport/passport_happy_46x49.png index f64e770e5..ba66d94fc 100644 Binary files a/assets/icons/Passport/passport_happy_46x49.png and b/assets/icons/Passport/passport_happy_46x49.png differ diff --git a/assets/icons/Passport/passport_okay_46x49.png b/assets/icons/Passport/passport_okay_46x49.png index 34fd3767b..62f39ba21 100644 Binary files a/assets/icons/Passport/passport_okay_46x49.png and b/assets/icons/Passport/passport_okay_46x49.png differ diff --git a/assets/icons/Power/BatteryBody_52x28.png b/assets/icons/Power/BatteryBody_52x28.png index 1fe568346..7f32403da 100644 Binary files a/assets/icons/Power/BatteryBody_52x28.png and b/assets/icons/Power/BatteryBody_52x28.png differ diff --git a/assets/icons/Power/Battery_16x16.png b/assets/icons/Power/Battery_16x16.png index 49af3c225..d59b884fa 100644 Binary files a/assets/icons/Power/Battery_16x16.png and b/assets/icons/Power/Battery_16x16.png differ diff --git a/assets/icons/Power/FaceCharging_29x14.png b/assets/icons/Power/FaceCharging_29x14.png index 106ededbf..7ee7f7414 100644 Binary files a/assets/icons/Power/FaceCharging_29x14.png and b/assets/icons/Power/FaceCharging_29x14.png differ diff --git a/assets/icons/Power/FaceConfused_29x14.png b/assets/icons/Power/FaceConfused_29x14.png index dcd2e3c67..0f07c8725 100644 Binary files a/assets/icons/Power/FaceConfused_29x14.png and b/assets/icons/Power/FaceConfused_29x14.png differ diff --git a/assets/icons/Power/FaceNopower_29x14.png b/assets/icons/Power/FaceNopower_29x14.png index f3da0c8ca..df9028d44 100644 Binary files a/assets/icons/Power/FaceNopower_29x14.png and b/assets/icons/Power/FaceNopower_29x14.png differ diff --git a/assets/icons/Power/FaceNormal_29x14.png b/assets/icons/Power/FaceNormal_29x14.png index 52d78c086..84e5d031f 100644 Binary files a/assets/icons/Power/FaceNormal_29x14.png and b/assets/icons/Power/FaceNormal_29x14.png differ diff --git a/assets/icons/Power/Health_16x16.png b/assets/icons/Power/Health_16x16.png index af343c520..8ef39f64a 100644 Binary files a/assets/icons/Power/Health_16x16.png and b/assets/icons/Power/Health_16x16.png differ diff --git a/assets/icons/Power/Temperature_16x16.png b/assets/icons/Power/Temperature_16x16.png index aade43882..7add41383 100644 Binary files a/assets/icons/Power/Temperature_16x16.png and b/assets/icons/Power/Temperature_16x16.png differ diff --git a/assets/icons/Power/Unplug_bg_bottom_128x10.png b/assets/icons/Power/Unplug_bg_bottom_128x10.png index 35d73ba76..18fd7bf9c 100644 Binary files a/assets/icons/Power/Unplug_bg_bottom_128x10.png and b/assets/icons/Power/Unplug_bg_bottom_128x10.png differ diff --git a/assets/icons/Power/Unplug_bg_top_128x14.png b/assets/icons/Power/Unplug_bg_top_128x14.png index bafa2c494..e9b697104 100644 Binary files a/assets/icons/Power/Unplug_bg_top_128x14.png and b/assets/icons/Power/Unplug_bg_top_128x14.png differ diff --git a/assets/icons/Power/Voltage_16x16.png b/assets/icons/Power/Voltage_16x16.png index 94e796872..4484e3af7 100644 Binary files a/assets/icons/Power/Voltage_16x16.png and b/assets/icons/Power/Voltage_16x16.png differ diff --git a/assets/icons/RFID/RFIDDolphinReceive_97x61.png b/assets/icons/RFID/RFIDDolphinReceive_97x61.png index e1f5f9f80..2b7abb85d 100644 Binary files a/assets/icons/RFID/RFIDDolphinReceive_97x61.png and b/assets/icons/RFID/RFIDDolphinReceive_97x61.png differ diff --git a/assets/icons/RFID/RFIDDolphinSend_97x61.png b/assets/icons/RFID/RFIDDolphinSend_97x61.png index 380a970d9..59b1dff88 100644 Binary files a/assets/icons/RFID/RFIDDolphinSend_97x61.png and b/assets/icons/RFID/RFIDDolphinSend_97x61.png differ diff --git a/assets/icons/RFID/RFIDSmallChip_14x14.png b/assets/icons/RFID/RFIDSmallChip_14x14.png index 24219a548..045c62518 100644 Binary files a/assets/icons/RFID/RFIDSmallChip_14x14.png and b/assets/icons/RFID/RFIDSmallChip_14x14.png differ diff --git a/assets/icons/SDCard/SDQuestion_35x43.png b/assets/icons/SDCard/SDQuestion_35x43.png index 257ab1d85..a07a98e4b 100644 Binary files a/assets/icons/SDCard/SDQuestion_35x43.png and b/assets/icons/SDCard/SDQuestion_35x43.png differ diff --git a/assets/icons/Settings/LoadingHourglass_24x24.png b/assets/icons/Settings/LoadingHourglass_24x24.png index 9c49dcad1..7fafe05ca 100644 Binary files a/assets/icons/Settings/LoadingHourglass_24x24.png and b/assets/icons/Settings/LoadingHourglass_24x24.png differ diff --git a/assets/icons/Settings/dolph_cry_49x54.png b/assets/icons/Settings/dolph_cry_49x54.png index 351a849b0..1ebb69e3e 100644 Binary files a/assets/icons/Settings/dolph_cry_49x54.png and b/assets/icons/Settings/dolph_cry_49x54.png differ diff --git a/assets/icons/Settings/qr_benchmark_25x25.png b/assets/icons/Settings/qr_benchmark_25x25.png index c5f9df119..908821b6b 100644 Binary files a/assets/icons/Settings/qr_benchmark_25x25.png and b/assets/icons/Settings/qr_benchmark_25x25.png differ diff --git a/assets/icons/StatusBar/BLE_beacon_7x8.png b/assets/icons/StatusBar/BLE_beacon_7x8.png index e8480287c..9f955de83 100644 Binary files a/assets/icons/StatusBar/BLE_beacon_7x8.png and b/assets/icons/StatusBar/BLE_beacon_7x8.png differ diff --git a/assets/icons/StatusBar/Background_128x11.png b/assets/icons/StatusBar/Background_128x11.png index 78ef029ae..b2fe0bb97 100644 Binary files a/assets/icons/StatusBar/Background_128x11.png and b/assets/icons/StatusBar/Background_128x11.png differ diff --git a/assets/icons/StatusBar/Battery_25x8.png b/assets/icons/StatusBar/Battery_25x8.png index 03187dc1f..bd185b730 100644 Binary files a/assets/icons/StatusBar/Battery_25x8.png and b/assets/icons/StatusBar/Battery_25x8.png differ diff --git a/assets/icons/StatusBar/Bluetooth_Connected_16x8.png b/assets/icons/StatusBar/Bluetooth_Connected_16x8.png index c77bc1494..667c6d892 100644 Binary files a/assets/icons/StatusBar/Bluetooth_Connected_16x8.png and b/assets/icons/StatusBar/Bluetooth_Connected_16x8.png differ diff --git a/assets/icons/StatusBar/Bluetooth_Idle_5x8.png b/assets/icons/StatusBar/Bluetooth_Idle_5x8.png index dc4a8733c..8d7b05ca0 100644 Binary files a/assets/icons/StatusBar/Bluetooth_Idle_5x8.png and b/assets/icons/StatusBar/Bluetooth_Idle_5x8.png differ diff --git a/assets/icons/StatusBar/Charging_lightning_9x10.png b/assets/icons/StatusBar/Charging_lightning_9x10.png index c2eaa47d0..0e4629ff5 100644 Binary files a/assets/icons/StatusBar/Charging_lightning_9x10.png and b/assets/icons/StatusBar/Charging_lightning_9x10.png differ diff --git a/assets/icons/StatusBar/Charging_lightning_mask_9x10.png b/assets/icons/StatusBar/Charging_lightning_mask_9x10.png index d44a32ae0..9c0cc455c 100644 Binary files a/assets/icons/StatusBar/Charging_lightning_mask_9x10.png and b/assets/icons/StatusBar/Charging_lightning_mask_9x10.png differ diff --git a/assets/icons/StatusBar/Exp_module_connected_12x8.png b/assets/icons/StatusBar/Exp_module_connected_12x8.png index a5f096682..fc136087b 100644 Binary files a/assets/icons/StatusBar/Exp_module_connected_12x8.png and b/assets/icons/StatusBar/Exp_module_connected_12x8.png differ diff --git a/assets/icons/StatusBar/Hidden_window_9x8.png b/assets/icons/StatusBar/Hidden_window_9x8.png index d6fc2b326..7fce0d5f6 100644 Binary files a/assets/icons/StatusBar/Hidden_window_9x8.png and b/assets/icons/StatusBar/Hidden_window_9x8.png differ diff --git a/assets/icons/StatusBar/Muted_8x8.png b/assets/icons/StatusBar/Muted_8x8.png index fee4e09f5..8d35be7fa 100644 Binary files a/assets/icons/StatusBar/Muted_8x8.png and b/assets/icons/StatusBar/Muted_8x8.png differ diff --git a/assets/icons/StatusBar/Rpc_active_7x8.png b/assets/icons/StatusBar/Rpc_active_7x8.png index f643a82aa..75ab10b4b 100644 Binary files a/assets/icons/StatusBar/Rpc_active_7x8.png and b/assets/icons/StatusBar/Rpc_active_7x8.png differ diff --git a/assets/icons/StatusBar/SDcardFail_11x8.png b/assets/icons/StatusBar/SDcardFail_11x8.png index 876cfa229..cad9c4fcc 100644 Binary files a/assets/icons/StatusBar/SDcardFail_11x8.png and b/assets/icons/StatusBar/SDcardFail_11x8.png differ diff --git a/assets/icons/StatusBar/SDcardMounted_11x8.png b/assets/icons/StatusBar/SDcardMounted_11x8.png index 68bc61921..3a3227adb 100644 Binary files a/assets/icons/StatusBar/SDcardMounted_11x8.png and b/assets/icons/StatusBar/SDcardMounted_11x8.png differ diff --git a/assets/icons/SubGhz/Cos_9x7.png b/assets/icons/SubGhz/Cos_9x7.png index 599ec0e58..7fba65cb2 100644 Binary files a/assets/icons/SubGhz/Cos_9x7.png and b/assets/icons/SubGhz/Cos_9x7.png differ diff --git a/assets/icons/SubGhz/Dynamic_9x7.png b/assets/icons/SubGhz/Dynamic_9x7.png index 50922d4fb..5f8fa4770 100644 Binary files a/assets/icons/SubGhz/Dynamic_9x7.png and b/assets/icons/SubGhz/Dynamic_9x7.png differ diff --git a/assets/icons/SubGhz/Fishing_123x52.png b/assets/icons/SubGhz/Fishing_123x52.png index 1e365de8f..abb06645b 100644 Binary files a/assets/icons/SubGhz/Fishing_123x52.png and b/assets/icons/SubGhz/Fishing_123x52.png differ diff --git a/assets/icons/SubGhz/Lock_7x8.png b/assets/icons/SubGhz/Lock_7x8.png index f7c9ca2c7..df07af6b8 100644 Binary files a/assets/icons/SubGhz/Lock_7x8.png and b/assets/icons/SubGhz/Lock_7x8.png differ diff --git a/assets/icons/SubGhz/MHz_25x11.png b/assets/icons/SubGhz/MHz_25x11.png index b99554956..2dae11a7e 100644 Binary files a/assets/icons/SubGhz/MHz_25x11.png and b/assets/icons/SubGhz/MHz_25x11.png differ diff --git a/assets/icons/SubGhz/Quest_7x8.png b/assets/icons/SubGhz/Quest_7x8.png index 6825247fb..95b4a7907 100644 Binary files a/assets/icons/SubGhz/Quest_7x8.png and b/assets/icons/SubGhz/Quest_7x8.png differ diff --git a/assets/icons/SubGhz/Raw_9x7.png b/assets/icons/SubGhz/Raw_9x7.png index 39a6d0386..b87cf51ab 100644 Binary files a/assets/icons/SubGhz/Raw_9x7.png and b/assets/icons/SubGhz/Raw_9x7.png differ diff --git a/assets/icons/SubGhz/Scanning_123x52.png b/assets/icons/SubGhz/Scanning_123x52.png index 485052c14..148d9aba8 100644 Binary files a/assets/icons/SubGhz/Scanning_123x52.png and b/assets/icons/SubGhz/Scanning_123x52.png differ diff --git a/assets/icons/SubGhz/Static_9x7.png b/assets/icons/SubGhz/Static_9x7.png index dad4833e3..0b658f852 100644 Binary files a/assets/icons/SubGhz/Static_9x7.png and b/assets/icons/SubGhz/Static_9x7.png differ diff --git a/assets/icons/SubGhz/Unlock_7x8.png b/assets/icons/SubGhz/Unlock_7x8.png index 9d82b4daf..da11e49cb 100644 Binary files a/assets/icons/SubGhz/Unlock_7x8.png and b/assets/icons/SubGhz/Unlock_7x8.png differ diff --git a/assets/icons/U2F/Auth_62x31.png b/assets/icons/U2F/Auth_62x31.png index 40f094ac9..0c22865b2 100644 Binary files a/assets/icons/U2F/Auth_62x31.png and b/assets/icons/U2F/Auth_62x31.png differ diff --git a/assets/icons/U2F/Connect_me_62x31.png b/assets/icons/U2F/Connect_me_62x31.png index 68c48c0e6..d7def86b0 100644 Binary files a/assets/icons/U2F/Connect_me_62x31.png and b/assets/icons/U2F/Connect_me_62x31.png differ diff --git a/assets/icons/U2F/Connected_62x31.png b/assets/icons/U2F/Connected_62x31.png index eeaf660b1..ee415989d 100644 Binary files a/assets/icons/U2F/Connected_62x31.png and b/assets/icons/U2F/Connected_62x31.png differ diff --git a/assets/icons/U2F/Drive_112x35.png b/assets/icons/U2F/Drive_112x35.png index 6f7b9c834..f2347925c 100644 Binary files a/assets/icons/U2F/Drive_112x35.png and b/assets/icons/U2F/Drive_112x35.png differ diff --git a/assets/icons/U2F/Error_62x31.png b/assets/icons/U2F/Error_62x31.png index bb280e751..c8b3b7a30 100644 Binary files a/assets/icons/U2F/Error_62x31.png and b/assets/icons/U2F/Error_62x31.png differ diff --git a/assets/icons/Update/Updating_32x40.png b/assets/icons/Update/Updating_32x40.png index d8f7654b8..ed1507323 100644 Binary files a/assets/icons/Update/Updating_32x40.png and b/assets/icons/Update/Updating_32x40.png differ diff --git a/assets/icons/Update/Updating_Logo_62x15.png b/assets/icons/Update/Updating_Logo_62x15.png index 50a749368..67db2e24b 100644 Binary files a/assets/icons/Update/Updating_Logo_62x15.png and b/assets/icons/Update/Updating_Logo_62x15.png differ diff --git a/assets/icons/iButton/iButtonDolphinVerySuccess_92x55.png b/assets/icons/iButton/iButtonDolphinVerySuccess_92x55.png index 0a85465cc..0d8263c5e 100644 Binary files a/assets/icons/iButton/iButtonDolphinVerySuccess_92x55.png and b/assets/icons/iButton/iButtonDolphinVerySuccess_92x55.png differ diff --git a/assets/icons/iButton/iButtonKey_49x44.png b/assets/icons/iButton/iButtonKey_49x44.png index db895ec52..d3bf6e20f 100644 Binary files a/assets/icons/iButton/iButtonKey_49x44.png and b/assets/icons/iButton/iButtonKey_49x44.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_0.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_0.png index 055618575..6e2986481 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_0.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_0.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_1.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_1.png index 8a9791cae..485254ee1 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_1.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_1.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_10.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_10.png index b266dc763..3ad5c1d0a 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_10.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_10.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_11.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_11.png index 00f572b44..882020550 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_11.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_11.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_12.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_12.png index 6f14b771e..a595af018 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_12.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_12.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_13.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_13.png index 11773d46e..994e6b57f 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_13.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_13.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_14.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_14.png index 667347940..6f5b5054a 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_14.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_14.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_15.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_15.png index 27e85a5f2..872ba414b 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_15.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_15.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_16.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_16.png index 3513072a0..5bf2b837e 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_16.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_16.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_17.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_17.png index ecb5d775a..c9aa508fd 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_17.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_17.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_18.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_18.png index f6f4d1ec8..144394bcb 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_18.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_18.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_19.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_19.png index b40979730..ec8db460a 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_19.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_19.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_2.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_2.png index befa38a39..864ff765a 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_2.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_2.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_20.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_20.png index c90df5a9c..af83806bf 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_20.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_20.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_21.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_21.png index b933c04c3..1f141ca29 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_21.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_21.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_22.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_22.png index 5668abc9a..fef49d42a 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_22.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_22.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_23.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_23.png index bee87ec12..6b0ecc423 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_23.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_23.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_24.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_24.png index c3dc6ef02..a44575ed2 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_24.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_24.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_25.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_25.png index 9eaa9277a..d9241638f 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_25.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_25.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_26.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_26.png index 508170e76..f730e9921 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_26.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_26.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_27.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_27.png index 0c8eff313..17368658e 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_27.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_27.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_28.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_28.png index 0528366e0..dfa6f9f14 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_28.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_28.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_29.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_29.png index df704a449..8bb99f461 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_29.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_29.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_3.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_3.png index cf3162f5f..0f8947ae8 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_3.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_3.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_30.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_30.png index d46c63645..a8daada7f 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_30.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_30.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_31.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_31.png index 37b0281d4..662b90783 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_31.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_31.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_32.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_32.png index d31ad12bc..c74c79485 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_32.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_32.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_33.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_33.png index 10b57138c..6493630ff 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_33.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_33.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_34.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_34.png index 7cb42dd65..bab2fa428 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_34.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_34.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_35.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_35.png index 38cb63465..8e3ffb27f 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_35.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_35.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_36.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_36.png index 0a000d740..64e41db05 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_36.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_36.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_37.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_37.png index c3589d31f..b18541b92 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_37.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_37.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_38.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_38.png index 964e25aa5..c022d0bd5 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_38.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_38.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_39.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_39.png index 4decc6b97..c01db4a8b 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_39.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_39.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_4.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_4.png index 27804f250..50538cf7e 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_4.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_4.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_40.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_40.png index 1a8d8b1d9..d30116083 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_40.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_40.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_41.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_41.png index 29a35c1b9..694782d88 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_41.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_41.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_42.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_42.png index 089365361..28d1b8640 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_42.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_42.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_5.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_5.png index 7799b20aa..5b56fd02a 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_5.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_5.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_6.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_6.png index 7cc929236..d8c212aa4 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_6.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_6.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_7.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_7.png index 29f8df8f9..796bfeefe 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_7.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_7.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_8.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_8.png index 926ff0911..a2d36fc74 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_8.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_8.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_9.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_9.png index 4f992440f..224c19485 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_9.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum1_128x64/frame_9.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_0.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_0.png index 055618575..6e2986481 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_0.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_0.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_1.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_1.png index 8a9791cae..485254ee1 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_1.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_1.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_10.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_10.png index b266dc763..3ad5c1d0a 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_10.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_10.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_11.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_11.png index 00f572b44..882020550 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_11.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_11.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_12.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_12.png index 6f14b771e..a595af018 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_12.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_12.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_13.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_13.png index 11773d46e..994e6b57f 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_13.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_13.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_14.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_14.png index 667347940..6f5b5054a 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_14.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_14.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_15.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_15.png index 27e85a5f2..872ba414b 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_15.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_15.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_16.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_16.png index 609da5c6e..8ba94f397 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_16.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_16.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_17.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_17.png index 389e94baa..63eac27ad 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_17.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_17.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_18.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_18.png index 1c67537cf..402aa112c 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_18.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_18.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_19.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_19.png index f2f4d2aa7..b1a492c97 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_19.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_19.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_2.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_2.png index befa38a39..864ff765a 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_2.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_2.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_20.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_20.png index 9ef9790f7..2aa6b53bc 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_20.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_20.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_21.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_21.png index abc131243..fc2abdbc6 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_21.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_21.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_22.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_22.png index baac41dc7..99b0d8c63 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_22.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_22.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_23.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_23.png index 524c78534..d99b2cc63 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_23.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_23.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_24.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_24.png index cd2ce13b0..0c45f6065 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_24.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_24.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_25.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_25.png index c91f67b9b..bd40a24a4 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_25.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_25.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_26.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_26.png index e952f09fe..ca74018f6 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_26.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_26.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_27.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_27.png index ac093214b..a9aac8f27 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_27.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_27.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_28.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_28.png index d3cd31e51..83b4a97d8 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_28.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_28.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_29.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_29.png index f2e2bc453..c712defa3 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_29.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_29.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_3.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_3.png index cf3162f5f..0f8947ae8 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_3.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_3.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_30.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_30.png index aa4e51bbc..5a38870d2 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_30.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_30.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_31.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_31.png index 75229f9c4..fcc672b14 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_31.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_31.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_32.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_32.png index c7b3348b7..dd4a2ddf4 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_32.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_32.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_33.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_33.png index 7d8bc6cf8..d33737184 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_33.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_33.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_34.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_34.png index 2dd3352d8..f0b43a99f 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_34.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_34.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_4.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_4.png index 27804f250..50538cf7e 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_4.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_4.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_5.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_5.png index 7799b20aa..5b56fd02a 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_5.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_5.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_6.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_6.png index 7cc929236..d8c212aa4 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_6.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_6.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_7.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_7.png index 29f8df8f9..796bfeefe 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_7.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_7.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_8.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_8.png index 926ff0911..a2d36fc74 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_8.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_8.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_9.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_9.png index 4f992440f..224c19485 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_9.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum2_128x64/frame_9.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_0.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_0.png index 055618575..6e2986481 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_0.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_0.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_1.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_1.png index 8a9791cae..485254ee1 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_1.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_1.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_10.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_10.png index b266dc763..3ad5c1d0a 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_10.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_10.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_11.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_11.png index 00f572b44..882020550 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_11.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_11.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_12.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_12.png index 6f14b771e..a595af018 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_12.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_12.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_13.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_13.png index 11773d46e..994e6b57f 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_13.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_13.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_14.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_14.png index 667347940..6f5b5054a 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_14.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_14.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_15.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_15.png index 27e85a5f2..872ba414b 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_15.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_15.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_16.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_16.png index 2fe9d4d82..c1b9db4f7 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_16.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_16.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_17.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_17.png index 407edc01a..1ba8ef2b6 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_17.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_17.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_18.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_18.png index 1be417331..91c649834 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_18.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_18.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_19.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_19.png index ceb4a1f81..11650dd5e 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_19.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_19.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_2.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_2.png index befa38a39..864ff765a 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_2.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_2.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_20.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_20.png index 3d11e2682..0c3d6f79d 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_20.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_20.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_21.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_21.png index f9b0e6f30..b3ba2976c 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_21.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_21.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_22.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_22.png index 6116575d2..e75565d92 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_22.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_22.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_23.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_23.png index 65731227e..eb26fc14b 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_23.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_23.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_24.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_24.png index b04b01022..563d74e17 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_24.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_24.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_25.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_25.png index 11700cc86..35c09dc74 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_25.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_25.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_26.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_26.png index 09f682ef0..ec46b19b1 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_26.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_26.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_27.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_27.png index d94772677..b8ad8d0be 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_27.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_27.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_28.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_28.png index 7ede5be12..190a4b447 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_28.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_28.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_29.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_29.png index 4cb438641..f68332ea6 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_29.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_29.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_3.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_3.png index cf3162f5f..0f8947ae8 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_3.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_3.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_30.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_30.png index b98badc41..85a9e5ed0 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_30.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_30.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_31.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_31.png index 59a88d76b..b447ac4d5 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_31.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_31.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_32.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_32.png index 0422eed15..2bb90398c 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_32.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_32.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_33.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_33.png index d78c42def..345f24600 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_33.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_33.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_34.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_34.png index 334c3d231..59a514d2f 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_34.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_34.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_35.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_35.png index a41323dd1..dfde0ac95 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_35.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_35.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_36.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_36.png index acac70e6c..1a59ba26a 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_36.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_36.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_37.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_37.png index 350929192..da0b7c4de 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_37.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_37.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_38.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_38.png index 1ee2294f8..0621c7d80 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_38.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_38.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_39.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_39.png index 1b3d3773d..92d8bf7e3 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_39.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_39.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_4.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_4.png index 27804f250..50538cf7e 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_4.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_4.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_5.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_5.png index 7799b20aa..5b56fd02a 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_5.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_5.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_6.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_6.png index 7cc929236..d8c212aa4 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_6.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_6.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_7.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_7.png index 29f8df8f9..796bfeefe 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_7.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_7.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_8.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_8.png index 926ff0911..a2d36fc74 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_8.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_8.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_9.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_9.png index 4f992440f..224c19485 100644 Binary files a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_9.png and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_9.png differ diff --git a/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_00.png b/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_00.png index 3242aa99d..a2f6fe0a6 100644 Binary files a/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_00.png and b/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_00.png differ diff --git a/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_01.png b/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_01.png index b79a058ea..fb9a8bdb0 100644 Binary files a/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_01.png and b/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_01.png differ diff --git a/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_02.png b/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_02.png index c163a0d99..45fc26155 100644 Binary files a/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_02.png and b/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_02.png differ diff --git a/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_03.png b/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_03.png index 2f85dba0c..9bd6b7f80 100644 Binary files a/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_03.png and b/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_03.png differ diff --git a/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_04.png b/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_04.png index cb66d6f5f..fb79bd003 100644 Binary files a/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_04.png and b/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_04.png differ diff --git a/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_05.png b/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_05.png index 29aa78fdb..ac8eb01bd 100644 Binary files a/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_05.png and b/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_05.png differ diff --git a/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_06.png b/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_06.png index 89a588fd1..aedd9b972 100644 Binary files a/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_06.png and b/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_06.png differ diff --git a/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_07.png b/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_07.png index 273bd8c63..e12d26f2b 100644 Binary files a/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_07.png and b/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_07.png differ diff --git a/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_08.png b/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_08.png index 24daceb20..1c0c4442e 100644 Binary files a/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_08.png and b/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_08.png differ diff --git a/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_09.png b/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_09.png index 3ed00d7b6..15e0d30a2 100644 Binary files a/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_09.png and b/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_09.png differ diff --git a/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_10.png b/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_10.png index 973fe64c7..6d57843cf 100644 Binary files a/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_10.png and b/assets/packs/Momentum/Icons/Animations/Levelup_128x64/frame_10.png differ diff --git a/assets/packs/Momentum/Icons/BLE/BLE_Pairing_128x64.png b/assets/packs/Momentum/Icons/BLE/BLE_Pairing_128x64.png index b281c12a3..44b410035 100644 Binary files a/assets/packs/Momentum/Icons/BLE/BLE_Pairing_128x64.png and b/assets/packs/Momentum/Icons/BLE/BLE_Pairing_128x64.png differ diff --git a/assets/packs/Momentum/Icons/Dolphin/DolphinDone_80x58.png b/assets/packs/Momentum/Icons/Dolphin/DolphinDone_80x58.png index 81a0e29ba..a29e03897 100644 Binary files a/assets/packs/Momentum/Icons/Dolphin/DolphinDone_80x58.png and b/assets/packs/Momentum/Icons/Dolphin/DolphinDone_80x58.png differ diff --git a/assets/packs/Momentum/Icons/Dolphin/DolphinMafia_119x62.png b/assets/packs/Momentum/Icons/Dolphin/DolphinMafia_119x62.png index ccaf12307..1348a697b 100644 Binary files a/assets/packs/Momentum/Icons/Dolphin/DolphinMafia_119x62.png and b/assets/packs/Momentum/Icons/Dolphin/DolphinMafia_119x62.png differ diff --git a/assets/packs/Momentum/Icons/Dolphin/DolphinReadingSuccess_59x63.png b/assets/packs/Momentum/Icons/Dolphin/DolphinReadingSuccess_59x63.png index b700ba94d..09c8858df 100644 Binary files a/assets/packs/Momentum/Icons/Dolphin/DolphinReadingSuccess_59x63.png and b/assets/packs/Momentum/Icons/Dolphin/DolphinReadingSuccess_59x63.png differ diff --git a/assets/packs/Momentum/Icons/Dolphin/DolphinSaved_92x58.png b/assets/packs/Momentum/Icons/Dolphin/DolphinSaved_92x58.png index 4b3aedaa9..96458f488 100644 Binary files a/assets/packs/Momentum/Icons/Dolphin/DolphinSaved_92x58.png and b/assets/packs/Momentum/Icons/Dolphin/DolphinSaved_92x58.png differ diff --git a/assets/packs/Momentum/Icons/Dolphin/DolphinSuccess_91x55.png b/assets/packs/Momentum/Icons/Dolphin/DolphinSuccess_91x55.png index 90b5befec..ae4edf26b 100644 Binary files a/assets/packs/Momentum/Icons/Dolphin/DolphinSuccess_91x55.png and b/assets/packs/Momentum/Icons/Dolphin/DolphinSuccess_91x55.png differ diff --git a/assets/packs/Momentum/Icons/Dolphin/DolphinWait_59x54.png b/assets/packs/Momentum/Icons/Dolphin/DolphinWait_59x54.png index 956a74a99..8741cb0bf 100644 Binary files a/assets/packs/Momentum/Icons/Dolphin/DolphinWait_59x54.png and b/assets/packs/Momentum/Icons/Dolphin/DolphinWait_59x54.png differ diff --git a/assets/packs/Momentum/Icons/Dolphin/WarningDolphinFlip_45x42.png b/assets/packs/Momentum/Icons/Dolphin/WarningDolphinFlip_45x42.png index 5595b606c..e7b5cbf23 100644 Binary files a/assets/packs/Momentum/Icons/Dolphin/WarningDolphinFlip_45x42.png and b/assets/packs/Momentum/Icons/Dolphin/WarningDolphinFlip_45x42.png differ diff --git a/assets/packs/Momentum/Icons/Dolphin/WarningDolphin_45x42.png b/assets/packs/Momentum/Icons/Dolphin/WarningDolphin_45x42.png index b254b6bca..6f6ba94ab 100644 Binary files a/assets/packs/Momentum/Icons/Dolphin/WarningDolphin_45x42.png and b/assets/packs/Momentum/Icons/Dolphin/WarningDolphin_45x42.png differ diff --git a/assets/packs/Momentum/Icons/Infrared/InfraredLearnShort_128x31.png b/assets/packs/Momentum/Icons/Infrared/InfraredLearnShort_128x31.png index 090d7d686..980602a66 100644 Binary files a/assets/packs/Momentum/Icons/Infrared/InfraredLearnShort_128x31.png and b/assets/packs/Momentum/Icons/Infrared/InfraredLearnShort_128x31.png differ diff --git a/assets/packs/Momentum/Icons/Interface/Lockscreen.png b/assets/packs/Momentum/Icons/Interface/Lockscreen.png index 3c25d73e8..38d3d4d50 100644 Binary files a/assets/packs/Momentum/Icons/Interface/Lockscreen.png and b/assets/packs/Momentum/Icons/Interface/Lockscreen.png differ diff --git a/assets/packs/Momentum/Icons/NFC/NFC_dolphin_emulation_51x64.png b/assets/packs/Momentum/Icons/NFC/NFC_dolphin_emulation_51x64.png index 853e95202..6934329a0 100644 Binary files a/assets/packs/Momentum/Icons/NFC/NFC_dolphin_emulation_51x64.png and b/assets/packs/Momentum/Icons/NFC/NFC_dolphin_emulation_51x64.png differ diff --git a/assets/packs/Momentum/Icons/Passport/passport_bad_46x49.png b/assets/packs/Momentum/Icons/Passport/passport_bad_46x49.png index 5e27db68c..4879ccf46 100644 Binary files a/assets/packs/Momentum/Icons/Passport/passport_bad_46x49.png and b/assets/packs/Momentum/Icons/Passport/passport_bad_46x49.png differ diff --git a/assets/packs/Momentum/Icons/Passport/passport_happy_46x49.png b/assets/packs/Momentum/Icons/Passport/passport_happy_46x49.png index 94e70ccbc..882d98470 100644 Binary files a/assets/packs/Momentum/Icons/Passport/passport_happy_46x49.png and b/assets/packs/Momentum/Icons/Passport/passport_happy_46x49.png differ diff --git a/assets/packs/Momentum/Icons/Passport/passport_okay_46x49.png b/assets/packs/Momentum/Icons/Passport/passport_okay_46x49.png index 6d96bcc0a..ca15867c6 100644 Binary files a/assets/packs/Momentum/Icons/Passport/passport_okay_46x49.png and b/assets/packs/Momentum/Icons/Passport/passport_okay_46x49.png differ diff --git a/assets/packs/Momentum/Icons/RFID/RFIDDolphinReceive_97x61.png b/assets/packs/Momentum/Icons/RFID/RFIDDolphinReceive_97x61.png index dacc6aae6..4244a8e95 100644 Binary files a/assets/packs/Momentum/Icons/RFID/RFIDDolphinReceive_97x61.png and b/assets/packs/Momentum/Icons/RFID/RFIDDolphinReceive_97x61.png differ diff --git a/assets/packs/Momentum/Icons/RFID/RFIDDolphinSend_97x61.png b/assets/packs/Momentum/Icons/RFID/RFIDDolphinSend_97x61.png index fd2ead2e3..ed518ae2e 100644 Binary files a/assets/packs/Momentum/Icons/RFID/RFIDDolphinSend_97x61.png and b/assets/packs/Momentum/Icons/RFID/RFIDDolphinSend_97x61.png differ diff --git a/assets/packs/Momentum/Icons/Settings/dolph_cry_49x54.png b/assets/packs/Momentum/Icons/Settings/dolph_cry_49x54.png index d1356cf88..fc23e2218 100644 Binary files a/assets/packs/Momentum/Icons/Settings/dolph_cry_49x54.png and b/assets/packs/Momentum/Icons/Settings/dolph_cry_49x54.png differ diff --git a/assets/packs/Momentum/Icons/SubGhz/Fishing_123x52.png b/assets/packs/Momentum/Icons/SubGhz/Fishing_123x52.png index ace3ac586..550061245 100644 Binary files a/assets/packs/Momentum/Icons/SubGhz/Fishing_123x52.png and b/assets/packs/Momentum/Icons/SubGhz/Fishing_123x52.png differ diff --git a/assets/packs/Momentum/Icons/SubGhz/Scanning_123x52.png b/assets/packs/Momentum/Icons/SubGhz/Scanning_123x52.png index adf91b8fd..6a2ca693d 100644 Binary files a/assets/packs/Momentum/Icons/SubGhz/Scanning_123x52.png and b/assets/packs/Momentum/Icons/SubGhz/Scanning_123x52.png differ diff --git a/assets/packs/Momentum/Icons/U2F/Auth_62x31.png b/assets/packs/Momentum/Icons/U2F/Auth_62x31.png index c138eaa3b..8f6652ad3 100644 Binary files a/assets/packs/Momentum/Icons/U2F/Auth_62x31.png and b/assets/packs/Momentum/Icons/U2F/Auth_62x31.png differ diff --git a/assets/packs/Momentum/Icons/U2F/Connect_me_62x31.png b/assets/packs/Momentum/Icons/U2F/Connect_me_62x31.png index 74785d202..db09ff98d 100644 Binary files a/assets/packs/Momentum/Icons/U2F/Connect_me_62x31.png and b/assets/packs/Momentum/Icons/U2F/Connect_me_62x31.png differ diff --git a/assets/packs/Momentum/Icons/U2F/Connected_62x31.png b/assets/packs/Momentum/Icons/U2F/Connected_62x31.png index b1100fc5a..998ccca59 100644 Binary files a/assets/packs/Momentum/Icons/U2F/Connected_62x31.png and b/assets/packs/Momentum/Icons/U2F/Connected_62x31.png differ diff --git a/assets/packs/Momentum/Icons/U2F/Error_62x31.png b/assets/packs/Momentum/Icons/U2F/Error_62x31.png index 3d85aa5d4..9034fb9de 100644 Binary files a/assets/packs/Momentum/Icons/U2F/Error_62x31.png and b/assets/packs/Momentum/Icons/U2F/Error_62x31.png differ diff --git a/assets/packs/Momentum/Icons/iButton/iButtonDolphinVerySuccess_92x55.png b/assets/packs/Momentum/Icons/iButton/iButtonDolphinVerySuccess_92x55.png index 0ae1403da..26b03bd6e 100644 Binary files a/assets/packs/Momentum/Icons/iButton/iButtonDolphinVerySuccess_92x55.png and b/assets/packs/Momentum/Icons/iButton/iButtonDolphinVerySuccess_92x55.png differ diff --git a/assets/packs/WatchDogs/Anims/BOTTY_CALL/frame_0.png b/assets/packs/WatchDogs/Anims/BOTTY_CALL/frame_0.png index 89f2c196d..994980160 100644 Binary files a/assets/packs/WatchDogs/Anims/BOTTY_CALL/frame_0.png and b/assets/packs/WatchDogs/Anims/BOTTY_CALL/frame_0.png differ diff --git a/assets/packs/WatchDogs/Anims/BOTTY_CALL/frame_1.png b/assets/packs/WatchDogs/Anims/BOTTY_CALL/frame_1.png index a102a5a2f..b77d9b13c 100644 Binary files a/assets/packs/WatchDogs/Anims/BOTTY_CALL/frame_1.png and b/assets/packs/WatchDogs/Anims/BOTTY_CALL/frame_1.png differ diff --git a/assets/packs/WatchDogs/Anims/BOTTY_CALL/frame_2.png b/assets/packs/WatchDogs/Anims/BOTTY_CALL/frame_2.png index c87f75126..cd0de12ab 100644 Binary files a/assets/packs/WatchDogs/Anims/BOTTY_CALL/frame_2.png and b/assets/packs/WatchDogs/Anims/BOTTY_CALL/frame_2.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_0.png b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_0.png index 84a8860e8..79b9180d5 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_0.png and b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_0.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_1.png b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_1.png index e1a05efe7..e89b4a1ce 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_1.png and b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_1.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_10.png b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_10.png index 8ca3fc196..48d9a34e3 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_10.png and b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_10.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_11.png b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_11.png index cc33eae2b..6b386762b 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_11.png and b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_11.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_12.png b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_12.png index b9e222ea6..2f6393470 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_12.png and b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_12.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_13.png b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_13.png index ba7e5d2f6..ee9fd6503 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_13.png and b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_13.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_14.png b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_14.png index b8c411f6d..8dc2abe49 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_14.png and b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_14.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_15.png b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_15.png index bd01a0089..66fa571cb 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_15.png and b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_15.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_16.png b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_16.png index d2d9691fc..f66d90a8a 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_16.png and b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_16.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_2.png b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_2.png index 34ec147a9..f0bb120d5 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_2.png and b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_2.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_3.png b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_3.png index 637268836..5b8d432e5 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_3.png and b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_3.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_4.png b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_4.png index 47d222eab..120267dd1 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_4.png and b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_4.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_5.png b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_5.png index 413cdfe39..176ffde5c 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_5.png and b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_5.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_6.png b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_6.png index ef177bda4..1fac48666 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_6.png and b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_6.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_7.png b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_7.png index b05c1d62c..62f83bdc3 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_7.png and b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_7.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_8.png b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_8.png index 413cdfe39..176ffde5c 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_8.png and b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_8.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_9.png b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_9.png index 800a9b63d..0086675d7 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_9.png and b/assets/packs/WatchDogs/Anims/DEDSEC_AD/frame_9.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_0.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_0.png index 72f4a6256..32b180df3 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_0.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_0.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_1.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_1.png index 85b9ca70a..a72ce9e56 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_1.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_1.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_10.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_10.png index 4315734b1..16d06aabf 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_10.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_10.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_11.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_11.png index 7b0643fda..9f6334234 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_11.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_11.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_12.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_12.png index 00d15664e..b64b8c536 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_12.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_12.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_13.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_13.png index a7b0b0350..fcb277b66 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_13.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_13.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_14.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_14.png index 1d602b70b..b139af646 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_14.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_14.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_15.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_15.png index 84719755a..55e5a9894 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_15.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_15.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_16.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_16.png index 88fa03a81..e12e8614a 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_16.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_16.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_17.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_17.png index 2a2a41929..70c1ebb6d 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_17.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_17.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_18.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_18.png index 9be47be36..1226bf993 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_18.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_18.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_19.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_19.png index bac895c6a..155f052eb 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_19.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_19.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_2.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_2.png index fd1764eed..a9a110d65 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_2.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_2.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_20.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_20.png index 6b5080348..9e1e24243 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_20.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_20.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_21.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_21.png index e5ae80185..3defc5d98 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_21.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_21.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_22.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_22.png index 7b399ee50..605609ece 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_22.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_22.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_23.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_23.png index db4dcc368..96e59e515 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_23.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_23.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_24.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_24.png index bd14e10d4..4b09b28e1 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_24.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_24.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_25.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_25.png index fff0885ba..56250c001 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_25.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_25.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_26.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_26.png index d51d807fa..0d614132f 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_26.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_26.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_27.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_27.png index 7f87ea182..19de08d59 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_27.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_27.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_28.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_28.png index f1d9447f4..3401ae8de 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_28.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_28.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_29.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_29.png index 1d173bceb..4655efbcd 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_29.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_29.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_3.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_3.png index f06d7da7f..833f34cb8 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_3.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_3.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_30.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_30.png index 3c5f59a7c..f41dfd455 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_30.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_30.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_31.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_31.png index a6bb50bcb..1e1bb2dbb 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_31.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_31.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_32.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_32.png index 8376e8ada..210e2f7ff 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_32.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_32.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_33.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_33.png index 46564c944..e2854e7a7 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_33.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_33.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_34.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_34.png index ddc72be20..33468e1d9 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_34.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_34.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_35.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_35.png index 192828c63..756629d0b 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_35.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_35.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_36.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_36.png index 5a39cc8f4..d8577daf8 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_36.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_36.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_37.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_37.png index 1df0d3fd5..174fbc40a 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_37.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_37.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_38.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_38.png index 612d13e64..2d6466093 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_38.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_38.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_39.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_39.png index 9bd001f81..79d85a4f7 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_39.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_39.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_4.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_4.png index ae563faf2..e5c8a38e5 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_4.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_4.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_40.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_40.png index 589566842..982cc0072 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_40.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_40.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_41.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_41.png index 1521a4074..39ce84076 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_41.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_41.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_5.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_5.png index f05234aad..700e35b29 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_5.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_5.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_6.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_6.png index 13850f72f..8a2f040c3 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_6.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_6.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_7.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_7.png index f0c8c4d3a..474a6438a 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_7.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_7.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_8.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_8.png index 10bcce799..7bf9aba08 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_8.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_8.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_9.png b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_9.png index 4bd2791ec..53d714283 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_9.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ANIM/frame_9.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_0.png b/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_0.png index f06b781dd..39ce84076 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_0.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_0.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_1.png b/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_1.png index a96802518..f233dca85 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_1.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_1.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_10.png b/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_10.png index 11cdc6413..35c4c59a0 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_10.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_10.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_2.png b/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_2.png index 0dbd6e391..b78ef36cd 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_2.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_2.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_3.png b/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_3.png index 318e7d8d1..e158609fb 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_3.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_3.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_4.png b/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_4.png index 7474d507b..710617784 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_4.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_4.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_5.png b/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_5.png index 9e321f463..d4d26a380 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_5.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_5.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_6.png b/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_6.png index 7fda8b293..9b65896c6 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_6.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_6.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_7.png b/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_7.png index 29019b856..bf7a10fbe 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_7.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_7.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_8.png b/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_8.png index 800337227..c642c5b43 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_8.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_8.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_9.png b/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_9.png index 53ec9c9e1..3d7ee92aa 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_9.png and b/assets/packs/WatchDogs/Anims/DEDSEC_ASCII/frame_9.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_0.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_0.png index 7c68b5c64..e653675cb 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_0.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_0.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_1.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_1.png index 9a69729cd..ef16a3ac1 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_1.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_1.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_10.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_10.png index 59499872f..764ed9196 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_10.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_10.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_11.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_11.png index 608cd51d3..6696d74f0 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_11.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_11.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_12.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_12.png index 2644b3f29..e717fc6a0 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_12.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_12.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_13.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_13.png index c1fafc5f3..3a2cf7413 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_13.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_13.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_14.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_14.png index 20ab84689..65b822d14 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_14.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_14.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_15.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_15.png index 39f1586df..a1a3c8ef2 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_15.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_15.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_16.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_16.png index 600d3fc9d..b8328f534 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_16.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_16.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_17.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_17.png index c1ea260e9..972ef942b 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_17.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_17.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_18.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_18.png index 5aa285bab..2e9bc1467 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_18.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_18.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_19.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_19.png index 578c8c68c..cf08107fd 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_19.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_19.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_2.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_2.png index b8a302853..e7e8b480f 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_2.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_2.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_20.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_20.png index 5ed8d680c..8fe9a1dcb 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_20.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_20.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_21.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_21.png index 4ee196640..73a80b35e 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_21.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_21.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_22.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_22.png index aa60355e4..150d9d05e 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_22.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_22.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_23.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_23.png index 2f8a2e1dd..fbd18a599 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_23.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_23.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_24.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_24.png index b8c38c7f4..4a73e007a 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_24.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_24.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_25.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_25.png index 3b77bc9f8..b3133a7db 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_25.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_25.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_26.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_26.png index 895ba22c9..5181c9cc5 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_26.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_26.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_27.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_27.png index b648d368f..24693b288 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_27.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_27.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_28.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_28.png index f2ae146c5..fba1043e6 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_28.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_28.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_29.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_29.png index 88b2e9874..124a11814 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_29.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_29.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_3.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_3.png index e2ba0172a..d58d72645 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_3.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_3.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_30.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_30.png index 9c651c7fa..b99d6eae1 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_30.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_30.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_31.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_31.png index bc860d94e..647915154 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_31.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_31.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_4.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_4.png index 2c2e4c1af..63b0e2bc4 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_4.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_4.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_5.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_5.png index 3f2523b7e..f6ff270f0 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_5.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_5.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_6.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_6.png index 5fcecb87d..0ead83ce6 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_6.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_6.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_7.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_7.png index 2ba761d98..e502c78c9 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_7.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_7.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_8.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_8.png index 9eeaaee60..77e2db417 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_8.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_8.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_9.png b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_9.png index 780c8e921..8bb16b121 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_9.png and b/assets/packs/WatchDogs/Anims/DEDSEC_LOGO/frame_9.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_0.png b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_0.png index 6e9e44054..9d27b4c2f 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_0.png and b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_0.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_1.png b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_1.png index 5acb5e5f3..e48f71ab3 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_1.png and b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_1.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_10.png b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_10.png index 4526961c1..029fed479 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_10.png and b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_10.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_11.png b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_11.png index 722800d87..232d31a99 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_11.png and b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_11.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_12.png b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_12.png index 6a48942f7..f93be86f9 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_12.png and b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_12.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_13.png b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_13.png index 2f0187928..29d65a6a4 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_13.png and b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_13.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_14.png b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_14.png index 589db0c77..e3cdf020c 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_14.png and b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_14.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_15.png b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_15.png index 4eda01bf3..a30fa48a5 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_15.png and b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_15.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_16.png b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_16.png index a3e22804a..549069adb 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_16.png and b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_16.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_17.png b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_17.png index 5fbf934f7..ef303e616 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_17.png and b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_17.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_18.png b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_18.png index 4eda01bf3..a30fa48a5 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_18.png and b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_18.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_19.png b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_19.png index 589db0c77..e3cdf020c 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_19.png and b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_19.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_2.png b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_2.png index 3ca753499..b552f4b56 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_2.png and b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_2.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_20.png b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_20.png index 4eda01bf3..a30fa48a5 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_20.png and b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_20.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_3.png b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_3.png index ecf8bc022..7497c1cda 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_3.png and b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_3.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_4.png b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_4.png index ecf8bc022..7497c1cda 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_4.png and b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_4.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_5.png b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_5.png index 0d24d7776..ae3e9af96 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_5.png and b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_5.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_6.png b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_6.png index c7a9236d2..b0042e5ed 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_6.png and b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_6.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_7.png b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_7.png index aa17d6355..dc07e5dca 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_7.png and b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_7.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_8.png b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_8.png index 824ee828e..3bbee9dde 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_8.png and b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_8.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_9.png b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_9.png index 1090e6390..aa63ade9d 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_9.png and b/assets/packs/WatchDogs/Anims/DEDSEC_OLD/frame_9.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_0.png b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_0.png index a98a3e97e..657d9db32 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_0.png and b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_0.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_1.png b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_1.png index 8d9f2304c..1203359fb 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_1.png and b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_1.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_10.png b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_10.png index 5e548cedf..16cac3eb9 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_10.png and b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_10.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_11.png b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_11.png index 741ddfb1f..fc49219fa 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_11.png and b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_11.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_12.png b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_12.png index 3822f3cdc..e0362e17f 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_12.png and b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_12.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_13.png b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_13.png index 31d548b87..8c14d93ff 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_13.png and b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_13.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_14.png b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_14.png index 8f044aaec..caf42900e 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_14.png and b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_14.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_15.png b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_15.png index 6e32ee563..12434487b 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_15.png and b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_15.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_16.png b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_16.png index ad9225909..eaf70610c 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_16.png and b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_16.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_17.png b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_17.png index 61fc86702..6e5b1d804 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_17.png and b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_17.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_2.png b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_2.png index 1076f4716..6e1983e3c 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_2.png and b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_2.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_3.png b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_3.png index d980f51a4..21478ab8f 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_3.png and b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_3.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_4.png b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_4.png index e06f0276c..65bbdbbf8 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_4.png and b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_4.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_5.png b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_5.png index 0c8afbf9e..2f539ae22 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_5.png and b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_5.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_6.png b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_6.png index c365129e7..692410193 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_6.png and b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_6.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_7.png b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_7.png index 7dcd3d35e..1c8076949 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_7.png and b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_7.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_8.png b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_8.png index 22b029b1c..ca04ff07c 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_8.png and b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_8.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_9.png b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_9.png index a6194d988..c911225c9 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_9.png and b/assets/packs/WatchDogs/Anims/DEDSEC_TALK/frame_9.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_0.png b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_0.png index 5a984b3fe..c06196679 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_0.png and b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_0.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_1.png b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_1.png index 464320e1b..f91dd303a 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_1.png and b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_1.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_10.png b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_10.png index e555bd825..49f758f31 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_10.png and b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_10.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_11.png b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_11.png index f321a49cc..ce1b5a7be 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_11.png and b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_11.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_12.png b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_12.png index 26514e26c..3e0941547 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_12.png and b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_12.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_13.png b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_13.png index f25efd6bc..bd79c102b 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_13.png and b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_13.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_14.png b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_14.png index c6d8d757b..7464c0bf9 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_14.png and b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_14.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_15.png b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_15.png index 63cba4303..da0b0bef2 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_15.png and b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_15.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_2.png b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_2.png index 9e4f4f6cd..5cb228106 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_2.png and b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_2.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_3.png b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_3.png index 3f86d2d22..88070df11 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_3.png and b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_3.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_4.png b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_4.png index 6c5e9d3aa..4de14b4e4 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_4.png and b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_4.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_5.png b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_5.png index 99c187050..9c2f3c5dc 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_5.png and b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_5.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_6.png b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_6.png index 7ce194f3c..4189a5897 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_6.png and b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_6.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_7.png b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_7.png index 977937e26..056960b5f 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_7.png and b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_7.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_8.png b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_8.png index fdb03d181..d121eb0d5 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_8.png and b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_8.png differ diff --git a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_9.png b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_9.png index f2f74aa55..317c4fbfe 100644 Binary files a/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_9.png and b/assets/packs/WatchDogs/Anims/DEDSEC_WAVE/frame_9.png differ diff --git a/assets/packs/WatchDogs/Anims/FINGER/frame_0.png b/assets/packs/WatchDogs/Anims/FINGER/frame_0.png index 31e214233..f10e4d3e1 100644 Binary files a/assets/packs/WatchDogs/Anims/FINGER/frame_0.png and b/assets/packs/WatchDogs/Anims/FINGER/frame_0.png differ diff --git a/assets/packs/WatchDogs/Anims/FINGER/frame_1.png b/assets/packs/WatchDogs/Anims/FINGER/frame_1.png index 9aefc5ccd..446b608bc 100644 Binary files a/assets/packs/WatchDogs/Anims/FINGER/frame_1.png and b/assets/packs/WatchDogs/Anims/FINGER/frame_1.png differ diff --git a/assets/packs/WatchDogs/Anims/FINGER/frame_2.png b/assets/packs/WatchDogs/Anims/FINGER/frame_2.png index 9a33e7cb5..7b393dcd8 100644 Binary files a/assets/packs/WatchDogs/Anims/FINGER/frame_2.png and b/assets/packs/WatchDogs/Anims/FINGER/frame_2.png differ diff --git a/assets/packs/WatchDogs/Anims/FINGER/frame_3.png b/assets/packs/WatchDogs/Anims/FINGER/frame_3.png index 330d92785..e6b72b39f 100644 Binary files a/assets/packs/WatchDogs/Anims/FINGER/frame_3.png and b/assets/packs/WatchDogs/Anims/FINGER/frame_3.png differ diff --git a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_0.png b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_0.png index 1de1eb799..87aa0b884 100644 Binary files a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_0.png and b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_0.png differ diff --git a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_1.png b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_1.png index e371e09f8..f609e86d0 100644 Binary files a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_1.png and b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_1.png differ diff --git a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_10.png b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_10.png index d6d347e91..6b96d6ebf 100644 Binary files a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_10.png and b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_10.png differ diff --git a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_11.png b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_11.png index db64d4360..ea4607af4 100644 Binary files a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_11.png and b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_11.png differ diff --git a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_12.png b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_12.png index ed2d5a88f..69f0c5bb3 100644 Binary files a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_12.png and b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_12.png differ diff --git a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_13.png b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_13.png index 6ad3e53d2..bab966f1c 100644 Binary files a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_13.png and b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_13.png differ diff --git a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_14.png b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_14.png index 4c3904dee..ca2662951 100644 Binary files a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_14.png and b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_14.png differ diff --git a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_15.png b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_15.png index 29e4ebc96..197c0ee62 100644 Binary files a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_15.png and b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_15.png differ diff --git a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_16.png b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_16.png index 933540182..8394c397d 100644 Binary files a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_16.png and b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_16.png differ diff --git a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_17.png b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_17.png index 3b2c6005c..06bdf2c7b 100644 Binary files a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_17.png and b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_17.png differ diff --git a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_18.png b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_18.png index a77629d71..635b2a176 100644 Binary files a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_18.png and b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_18.png differ diff --git a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_19.png b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_19.png index 1d2bfa9ec..adc282832 100644 Binary files a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_19.png and b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_19.png differ diff --git a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_2.png b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_2.png index d6c5135f7..f5730c7ff 100644 Binary files a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_2.png and b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_2.png differ diff --git a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_20.png b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_20.png index adc99f125..ccfbdb3be 100644 Binary files a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_20.png and b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_20.png differ diff --git a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_21.png b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_21.png index 8e2359a9c..2f123e8a5 100644 Binary files a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_21.png and b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_21.png differ diff --git a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_3.png b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_3.png index a7523702b..4bebf7b20 100644 Binary files a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_3.png and b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_3.png differ diff --git a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_4.png b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_4.png index a9db6a3ec..35d0be0dd 100644 Binary files a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_4.png and b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_4.png differ diff --git a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_5.png b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_5.png index bc2c2bfa5..506972937 100644 Binary files a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_5.png and b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_5.png differ diff --git a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_6.png b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_6.png index 1d3844ba2..d9102ce23 100644 Binary files a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_6.png and b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_6.png differ diff --git a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_7.png b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_7.png index d4891052d..959f2117e 100644 Binary files a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_7.png and b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_7.png differ diff --git a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_8.png b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_8.png index 60de906f2..305ec2b07 100644 Binary files a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_8.png and b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_8.png differ diff --git a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_9.png b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_9.png index f2cb5351d..33293b0eb 100644 Binary files a/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_9.png and b/assets/packs/WatchDogs/Anims/GUNS_CAR/frame_9.png differ diff --git a/assets/packs/WatchDogs/Anims/HANDS/frame_0.png b/assets/packs/WatchDogs/Anims/HANDS/frame_0.png index 80a686234..3ec56807d 100644 Binary files a/assets/packs/WatchDogs/Anims/HANDS/frame_0.png and b/assets/packs/WatchDogs/Anims/HANDS/frame_0.png differ diff --git a/assets/packs/WatchDogs/Anims/HANDS/frame_1.png b/assets/packs/WatchDogs/Anims/HANDS/frame_1.png index a7ed6a713..d905eca38 100644 Binary files a/assets/packs/WatchDogs/Anims/HANDS/frame_1.png and b/assets/packs/WatchDogs/Anims/HANDS/frame_1.png differ diff --git a/assets/packs/WatchDogs/Anims/HANDS/frame_2.png b/assets/packs/WatchDogs/Anims/HANDS/frame_2.png index f07808ca1..b192a72e5 100644 Binary files a/assets/packs/WatchDogs/Anims/HANDS/frame_2.png and b/assets/packs/WatchDogs/Anims/HANDS/frame_2.png differ diff --git a/assets/packs/WatchDogs/Anims/HANDS/frame_3.png b/assets/packs/WatchDogs/Anims/HANDS/frame_3.png index 68001742e..28cc33951 100644 Binary files a/assets/packs/WatchDogs/Anims/HANDS/frame_3.png and b/assets/packs/WatchDogs/Anims/HANDS/frame_3.png differ diff --git a/assets/packs/WatchDogs/Anims/HANDS/frame_4.png b/assets/packs/WatchDogs/Anims/HANDS/frame_4.png index f22c71e4f..af8e9d7d2 100644 Binary files a/assets/packs/WatchDogs/Anims/HANDS/frame_4.png and b/assets/packs/WatchDogs/Anims/HANDS/frame_4.png differ diff --git a/assets/packs/WatchDogs/Anims/HANDS/frame_5.png b/assets/packs/WatchDogs/Anims/HANDS/frame_5.png index 1626ec7eb..d13bce2d5 100644 Binary files a/assets/packs/WatchDogs/Anims/HANDS/frame_5.png and b/assets/packs/WatchDogs/Anims/HANDS/frame_5.png differ diff --git a/assets/packs/WatchDogs/Anims/HANDS/frame_6.png b/assets/packs/WatchDogs/Anims/HANDS/frame_6.png index d2fe2859d..2214a0b04 100644 Binary files a/assets/packs/WatchDogs/Anims/HANDS/frame_6.png and b/assets/packs/WatchDogs/Anims/HANDS/frame_6.png differ diff --git a/assets/packs/WatchDogs/Anims/JOIN_US/frame_0.png b/assets/packs/WatchDogs/Anims/JOIN_US/frame_0.png index e9ec089bd..45819196d 100644 Binary files a/assets/packs/WatchDogs/Anims/JOIN_US/frame_0.png and b/assets/packs/WatchDogs/Anims/JOIN_US/frame_0.png differ diff --git a/assets/packs/WatchDogs/Anims/JOIN_US/frame_1.png b/assets/packs/WatchDogs/Anims/JOIN_US/frame_1.png index d63fb1a62..147c55638 100644 Binary files a/assets/packs/WatchDogs/Anims/JOIN_US/frame_1.png and b/assets/packs/WatchDogs/Anims/JOIN_US/frame_1.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_0.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_0.png index 3c5da572b..39ce84076 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_0.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_0.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_1.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_1.png index 1521a4074..39ce84076 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_1.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_1.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_10.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_10.png index 8ceef48df..beddd3d59 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_10.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_10.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_11.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_11.png index 0d0c9ebd0..3338ebbcd 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_11.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_11.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_12.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_12.png index 81d1e7de4..34a1f8f5b 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_12.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_12.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_13.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_13.png index d71fafd91..c0827fd9c 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_13.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_13.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_14.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_14.png index db3c1e13b..8974954f5 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_14.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_14.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_15.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_15.png index 349c118e2..4f697db23 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_15.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_15.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_16.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_16.png index d9f43514d..ba7992344 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_16.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_16.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_17.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_17.png index 27de431a8..301578c09 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_17.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_17.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_18.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_18.png index dfbffeccf..499518d65 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_18.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_18.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_19.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_19.png index d2c9252ca..af24aff8c 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_19.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_19.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_2.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_2.png index c0ac00aeb..28f0b5e57 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_2.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_2.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_20.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_20.png index d2b1ed935..93ac4c9f8 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_20.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_20.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_21.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_21.png index da83a3664..533c5eea1 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_21.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_21.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_22.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_22.png index 3ddb22e97..9b760a372 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_22.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_22.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_23.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_23.png index 1c8770737..7973278b2 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_23.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_23.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_24.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_24.png index 1521a4074..39ce84076 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_24.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_24.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_25.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_25.png index 7fd19087c..902503dd4 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_25.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_25.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_26.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_26.png index 1521a4074..39ce84076 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_26.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_26.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_27.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_27.png index 01b1cb1e0..39ce84076 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_27.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_27.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_28.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_28.png index 534604c26..3564761c1 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_28.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_28.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_29.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_29.png index 1521a4074..39ce84076 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_29.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_29.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_3.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_3.png index 7aacdfc57..c62e618fe 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_3.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_3.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_30.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_30.png index 1521a4074..39ce84076 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_30.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_30.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_4.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_4.png index 1521a4074..39ce84076 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_4.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_4.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_5.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_5.png index 38566222f..45103e40f 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_5.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_5.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_6.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_6.png index b92ba5c74..6c5c39e69 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_6.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_6.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_7.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_7.png index 71095643b..33bd7448f 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_7.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_7.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_8.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_8.png index 1c8db93f4..392fe42e0 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_8.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_8.png differ diff --git a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_9.png b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_9.png index eef209b33..51800d27c 100644 Binary files a/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_9.png and b/assets/packs/WatchDogs/Anims/LOGO_WD2/frame_9.png differ diff --git a/assets/packs/WatchDogs/Anims/MARCUS/frame_0.png b/assets/packs/WatchDogs/Anims/MARCUS/frame_0.png index a9d12865c..1b6a13884 100644 Binary files a/assets/packs/WatchDogs/Anims/MARCUS/frame_0.png and b/assets/packs/WatchDogs/Anims/MARCUS/frame_0.png differ diff --git a/assets/packs/WatchDogs/Anims/MARCUS/frame_1.png b/assets/packs/WatchDogs/Anims/MARCUS/frame_1.png index f095bc1b1..7c0334f65 100644 Binary files a/assets/packs/WatchDogs/Anims/MARCUS/frame_1.png and b/assets/packs/WatchDogs/Anims/MARCUS/frame_1.png differ diff --git a/assets/packs/WatchDogs/Anims/MARCUS/frame_10.png b/assets/packs/WatchDogs/Anims/MARCUS/frame_10.png index cf3985ed8..34c08716e 100644 Binary files a/assets/packs/WatchDogs/Anims/MARCUS/frame_10.png and b/assets/packs/WatchDogs/Anims/MARCUS/frame_10.png differ diff --git a/assets/packs/WatchDogs/Anims/MARCUS/frame_11.png b/assets/packs/WatchDogs/Anims/MARCUS/frame_11.png index dadb73cf0..b49f3b903 100644 Binary files a/assets/packs/WatchDogs/Anims/MARCUS/frame_11.png and b/assets/packs/WatchDogs/Anims/MARCUS/frame_11.png differ diff --git a/assets/packs/WatchDogs/Anims/MARCUS/frame_12.png b/assets/packs/WatchDogs/Anims/MARCUS/frame_12.png index 926726e10..e81af01cf 100644 Binary files a/assets/packs/WatchDogs/Anims/MARCUS/frame_12.png and b/assets/packs/WatchDogs/Anims/MARCUS/frame_12.png differ diff --git a/assets/packs/WatchDogs/Anims/MARCUS/frame_13.png b/assets/packs/WatchDogs/Anims/MARCUS/frame_13.png index 94aee738b..a4546de10 100644 Binary files a/assets/packs/WatchDogs/Anims/MARCUS/frame_13.png and b/assets/packs/WatchDogs/Anims/MARCUS/frame_13.png differ diff --git a/assets/packs/WatchDogs/Anims/MARCUS/frame_14.png b/assets/packs/WatchDogs/Anims/MARCUS/frame_14.png index ace6e4109..64557320f 100644 Binary files a/assets/packs/WatchDogs/Anims/MARCUS/frame_14.png and b/assets/packs/WatchDogs/Anims/MARCUS/frame_14.png differ diff --git a/assets/packs/WatchDogs/Anims/MARCUS/frame_15.png b/assets/packs/WatchDogs/Anims/MARCUS/frame_15.png index 7c8478b22..2f7ebaba0 100644 Binary files a/assets/packs/WatchDogs/Anims/MARCUS/frame_15.png and b/assets/packs/WatchDogs/Anims/MARCUS/frame_15.png differ diff --git a/assets/packs/WatchDogs/Anims/MARCUS/frame_16.png b/assets/packs/WatchDogs/Anims/MARCUS/frame_16.png index ab4fed561..23e556bda 100644 Binary files a/assets/packs/WatchDogs/Anims/MARCUS/frame_16.png and b/assets/packs/WatchDogs/Anims/MARCUS/frame_16.png differ diff --git a/assets/packs/WatchDogs/Anims/MARCUS/frame_17.png b/assets/packs/WatchDogs/Anims/MARCUS/frame_17.png index d00c23db4..fc3ce5af6 100644 Binary files a/assets/packs/WatchDogs/Anims/MARCUS/frame_17.png and b/assets/packs/WatchDogs/Anims/MARCUS/frame_17.png differ diff --git a/assets/packs/WatchDogs/Anims/MARCUS/frame_18.png b/assets/packs/WatchDogs/Anims/MARCUS/frame_18.png index b7d0fd275..b14e2eb89 100644 Binary files a/assets/packs/WatchDogs/Anims/MARCUS/frame_18.png and b/assets/packs/WatchDogs/Anims/MARCUS/frame_18.png differ diff --git a/assets/packs/WatchDogs/Anims/MARCUS/frame_19.png b/assets/packs/WatchDogs/Anims/MARCUS/frame_19.png index e1bbfce92..199670f40 100644 Binary files a/assets/packs/WatchDogs/Anims/MARCUS/frame_19.png and b/assets/packs/WatchDogs/Anims/MARCUS/frame_19.png differ diff --git a/assets/packs/WatchDogs/Anims/MARCUS/frame_2.png b/assets/packs/WatchDogs/Anims/MARCUS/frame_2.png index 041405694..20a857b43 100644 Binary files a/assets/packs/WatchDogs/Anims/MARCUS/frame_2.png and b/assets/packs/WatchDogs/Anims/MARCUS/frame_2.png differ diff --git a/assets/packs/WatchDogs/Anims/MARCUS/frame_20.png b/assets/packs/WatchDogs/Anims/MARCUS/frame_20.png index c40f70240..b81bed668 100644 Binary files a/assets/packs/WatchDogs/Anims/MARCUS/frame_20.png and b/assets/packs/WatchDogs/Anims/MARCUS/frame_20.png differ diff --git a/assets/packs/WatchDogs/Anims/MARCUS/frame_21.png b/assets/packs/WatchDogs/Anims/MARCUS/frame_21.png index c35481532..36a458355 100644 Binary files a/assets/packs/WatchDogs/Anims/MARCUS/frame_21.png and b/assets/packs/WatchDogs/Anims/MARCUS/frame_21.png differ diff --git a/assets/packs/WatchDogs/Anims/MARCUS/frame_22.png b/assets/packs/WatchDogs/Anims/MARCUS/frame_22.png index c641b77bf..9a2973b53 100644 Binary files a/assets/packs/WatchDogs/Anims/MARCUS/frame_22.png and b/assets/packs/WatchDogs/Anims/MARCUS/frame_22.png differ diff --git a/assets/packs/WatchDogs/Anims/MARCUS/frame_23.png b/assets/packs/WatchDogs/Anims/MARCUS/frame_23.png index 4fd396da2..e1018c0ea 100644 Binary files a/assets/packs/WatchDogs/Anims/MARCUS/frame_23.png and b/assets/packs/WatchDogs/Anims/MARCUS/frame_23.png differ diff --git a/assets/packs/WatchDogs/Anims/MARCUS/frame_3.png b/assets/packs/WatchDogs/Anims/MARCUS/frame_3.png index b19705754..d9c9ccd39 100644 Binary files a/assets/packs/WatchDogs/Anims/MARCUS/frame_3.png and b/assets/packs/WatchDogs/Anims/MARCUS/frame_3.png differ diff --git a/assets/packs/WatchDogs/Anims/MARCUS/frame_4.png b/assets/packs/WatchDogs/Anims/MARCUS/frame_4.png index f78254d1e..386594f1d 100644 Binary files a/assets/packs/WatchDogs/Anims/MARCUS/frame_4.png and b/assets/packs/WatchDogs/Anims/MARCUS/frame_4.png differ diff --git a/assets/packs/WatchDogs/Anims/MARCUS/frame_5.png b/assets/packs/WatchDogs/Anims/MARCUS/frame_5.png index cd9f29873..c62422d67 100644 Binary files a/assets/packs/WatchDogs/Anims/MARCUS/frame_5.png and b/assets/packs/WatchDogs/Anims/MARCUS/frame_5.png differ diff --git a/assets/packs/WatchDogs/Anims/MARCUS/frame_6.png b/assets/packs/WatchDogs/Anims/MARCUS/frame_6.png index 038928359..fcef4dd99 100644 Binary files a/assets/packs/WatchDogs/Anims/MARCUS/frame_6.png and b/assets/packs/WatchDogs/Anims/MARCUS/frame_6.png differ diff --git a/assets/packs/WatchDogs/Anims/MARCUS/frame_7.png b/assets/packs/WatchDogs/Anims/MARCUS/frame_7.png index 8b107952f..7d516b82f 100644 Binary files a/assets/packs/WatchDogs/Anims/MARCUS/frame_7.png and b/assets/packs/WatchDogs/Anims/MARCUS/frame_7.png differ diff --git a/assets/packs/WatchDogs/Anims/MARCUS/frame_8.png b/assets/packs/WatchDogs/Anims/MARCUS/frame_8.png index 97e0c5d21..fbb5e0956 100644 Binary files a/assets/packs/WatchDogs/Anims/MARCUS/frame_8.png and b/assets/packs/WatchDogs/Anims/MARCUS/frame_8.png differ diff --git a/assets/packs/WatchDogs/Anims/MARCUS/frame_9.png b/assets/packs/WatchDogs/Anims/MARCUS/frame_9.png index e40ac44f7..14d93f835 100644 Binary files a/assets/packs/WatchDogs/Anims/MARCUS/frame_9.png and b/assets/packs/WatchDogs/Anims/MARCUS/frame_9.png differ diff --git a/assets/packs/WatchDogs/Anims/MUMMY/frame_0.png b/assets/packs/WatchDogs/Anims/MUMMY/frame_0.png index 57e428ae1..2514823ea 100644 Binary files a/assets/packs/WatchDogs/Anims/MUMMY/frame_0.png and b/assets/packs/WatchDogs/Anims/MUMMY/frame_0.png differ diff --git a/assets/packs/WatchDogs/Anims/MUMMY/frame_1.png b/assets/packs/WatchDogs/Anims/MUMMY/frame_1.png index 455d14230..ef0a98b63 100644 Binary files a/assets/packs/WatchDogs/Anims/MUMMY/frame_1.png and b/assets/packs/WatchDogs/Anims/MUMMY/frame_1.png differ diff --git a/assets/packs/WatchDogs/Anims/MUMMY/frame_2.png b/assets/packs/WatchDogs/Anims/MUMMY/frame_2.png index 33f13a62c..639306963 100644 Binary files a/assets/packs/WatchDogs/Anims/MUMMY/frame_2.png and b/assets/packs/WatchDogs/Anims/MUMMY/frame_2.png differ diff --git a/assets/packs/WatchDogs/Anims/MUMMY/frame_3.png b/assets/packs/WatchDogs/Anims/MUMMY/frame_3.png index b43a97664..958522def 100644 Binary files a/assets/packs/WatchDogs/Anims/MUMMY/frame_3.png and b/assets/packs/WatchDogs/Anims/MUMMY/frame_3.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_0.png b/assets/packs/WatchDogs/Anims/REAPER/frame_0.png index 0e3121049..aa609552b 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_0.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_0.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_1.png b/assets/packs/WatchDogs/Anims/REAPER/frame_1.png index af05489ac..12093ee28 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_1.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_1.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_10.png b/assets/packs/WatchDogs/Anims/REAPER/frame_10.png index e51864e6c..b2c13ff32 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_10.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_10.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_11.png b/assets/packs/WatchDogs/Anims/REAPER/frame_11.png index ff85eb9d8..111282a8b 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_11.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_11.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_12.png b/assets/packs/WatchDogs/Anims/REAPER/frame_12.png index d27165572..d63c578f9 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_12.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_12.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_13.png b/assets/packs/WatchDogs/Anims/REAPER/frame_13.png index 1dfd3ca90..63e8896f9 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_13.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_13.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_14.png b/assets/packs/WatchDogs/Anims/REAPER/frame_14.png index 77c31b296..d90a6c428 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_14.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_14.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_15.png b/assets/packs/WatchDogs/Anims/REAPER/frame_15.png index f6b9e83b9..f8ee139c4 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_15.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_15.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_16.png b/assets/packs/WatchDogs/Anims/REAPER/frame_16.png index 1af1e42b2..2e32c3db4 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_16.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_16.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_17.png b/assets/packs/WatchDogs/Anims/REAPER/frame_17.png index 5316af01f..69a93c91b 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_17.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_17.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_18.png b/assets/packs/WatchDogs/Anims/REAPER/frame_18.png index b70af3eee..d33be3bf3 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_18.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_18.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_19.png b/assets/packs/WatchDogs/Anims/REAPER/frame_19.png index 49fe9749a..802ca08bc 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_19.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_19.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_2.png b/assets/packs/WatchDogs/Anims/REAPER/frame_2.png index 4c00f5c33..80de53d92 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_2.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_2.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_20.png b/assets/packs/WatchDogs/Anims/REAPER/frame_20.png index 82343d600..cb5ecaf06 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_20.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_20.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_21.png b/assets/packs/WatchDogs/Anims/REAPER/frame_21.png index 8de989381..4f7a1ceaf 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_21.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_21.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_22.png b/assets/packs/WatchDogs/Anims/REAPER/frame_22.png index 4e66988e3..8346730c0 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_22.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_22.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_23.png b/assets/packs/WatchDogs/Anims/REAPER/frame_23.png index 54e58d1ee..d4f4864bd 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_23.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_23.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_24.png b/assets/packs/WatchDogs/Anims/REAPER/frame_24.png index 89387f71e..d7aecdd46 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_24.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_24.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_25.png b/assets/packs/WatchDogs/Anims/REAPER/frame_25.png index 7a678691a..2a24de9d4 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_25.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_25.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_26.png b/assets/packs/WatchDogs/Anims/REAPER/frame_26.png index a81a51793..70b64fa5c 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_26.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_26.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_27.png b/assets/packs/WatchDogs/Anims/REAPER/frame_27.png index 6abea9a9a..2c45b9e3d 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_27.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_27.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_28.png b/assets/packs/WatchDogs/Anims/REAPER/frame_28.png index e9810705c..7975b9a5c 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_28.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_28.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_29.png b/assets/packs/WatchDogs/Anims/REAPER/frame_29.png index 37bc0de0f..4cd034ca2 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_29.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_29.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_3.png b/assets/packs/WatchDogs/Anims/REAPER/frame_3.png index b66d9e93d..bf3843e7a 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_3.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_3.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_30.png b/assets/packs/WatchDogs/Anims/REAPER/frame_30.png index 8a11e4e6b..39ce84076 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_30.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_30.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_31.png b/assets/packs/WatchDogs/Anims/REAPER/frame_31.png index 5c4971b0d..39ce84076 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_31.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_31.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_4.png b/assets/packs/WatchDogs/Anims/REAPER/frame_4.png index 18cf2906e..2c4abbeb0 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_4.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_4.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_5.png b/assets/packs/WatchDogs/Anims/REAPER/frame_5.png index 30c9ddef4..834ae8d1d 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_5.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_5.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_6.png b/assets/packs/WatchDogs/Anims/REAPER/frame_6.png index b276b7505..49664c659 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_6.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_6.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_7.png b/assets/packs/WatchDogs/Anims/REAPER/frame_7.png index d590c76cd..4e5938dac 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_7.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_7.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_8.png b/assets/packs/WatchDogs/Anims/REAPER/frame_8.png index 18f5c86f3..f964647cb 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_8.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_8.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER/frame_9.png b/assets/packs/WatchDogs/Anims/REAPER/frame_9.png index fcfd84315..536995e12 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER/frame_9.png and b/assets/packs/WatchDogs/Anims/REAPER/frame_9.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_0.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_0.png index 795de4dae..863c6e859 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_0.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_0.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_1.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_1.png index 82b6533b3..abec6281b 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_1.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_1.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_10.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_10.png index 190a71135..964910cd4 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_10.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_10.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_11.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_11.png index b1012f221..fba3c618f 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_11.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_11.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_12.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_12.png index 5a4577598..7635db78d 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_12.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_12.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_13.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_13.png index 2457bac03..545cd86f3 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_13.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_13.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_14.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_14.png index 5fbdecabc..52b5a8f70 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_14.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_14.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_15.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_15.png index 48fbe1a87..dcc682798 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_15.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_15.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_16.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_16.png index de15b64c1..71dc7f509 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_16.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_16.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_17.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_17.png index f40ae6d67..9184d276a 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_17.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_17.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_18.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_18.png index faa86e2c0..2bfe1cd2c 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_18.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_18.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_19.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_19.png index ee5a97cf3..d8cbbc78a 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_19.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_19.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_2.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_2.png index 33925efdd..ce4e3b72c 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_2.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_2.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_20.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_20.png index 3874d7f4d..07f968f40 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_20.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_20.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_21.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_21.png index 1de161347..d6f547c51 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_21.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_21.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_22.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_22.png index 8acdbd714..47fdb676f 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_22.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_22.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_23.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_23.png index ef019a5fa..706bae857 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_23.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_23.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_24.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_24.png index 05ae11fb8..3d0200be1 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_24.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_24.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_25.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_25.png index 38668cbe4..117d8917b 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_25.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_25.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_26.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_26.png index ba640f555..669cc361d 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_26.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_26.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_27.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_27.png index 7c428c523..f556e946e 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_27.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_27.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_28.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_28.png index 2bc3dad18..789caa07a 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_28.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_28.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_29.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_29.png index e3bd98993..f488ab565 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_29.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_29.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_3.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_3.png index 32dca0e44..e5e248f0f 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_3.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_3.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_30.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_30.png index e38cb3c71..29eb3b927 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_30.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_30.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_31.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_31.png index 4f6a98e8d..21092d2bc 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_31.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_31.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_32.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_32.png index 0d2caaf82..e3eabfcc0 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_32.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_32.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_33.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_33.png index b0a49ec01..73a08ab1e 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_33.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_33.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_34.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_34.png index f22934689..4a13c1629 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_34.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_34.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_35.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_35.png index 5a0701c73..1ef2200db 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_35.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_35.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_36.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_36.png index ccee3f5c1..e98f0011b 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_36.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_36.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_37.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_37.png index 3d1d8269e..6e700c296 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_37.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_37.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_38.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_38.png index 8dcbcc5d6..a6af44448 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_38.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_38.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_39.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_39.png index e673f254c..74332e0ac 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_39.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_39.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_4.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_4.png index cb48826d7..ea97ad4b4 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_4.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_4.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_40.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_40.png index 343c4ddbd..424472203 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_40.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_40.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_41.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_41.png index 704f7dfa4..13fbcefcc 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_41.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_41.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_5.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_5.png index 5e5a9481a..83a7aab25 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_5.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_5.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_6.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_6.png index ed0507efc..37909fe79 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_6.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_6.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_7.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_7.png index 87c0d22c8..8d38db931 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_7.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_7.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_8.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_8.png index 3e0d8d046..88c0ff43f 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_8.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_8.png differ diff --git a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_9.png b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_9.png index 931ed5876..d98909e78 100644 Binary files a/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_9.png and b/assets/packs/WatchDogs/Anims/REAPER_ALT/frame_9.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_0.png b/assets/packs/WatchDogs/Anims/SKULL/frame_0.png index aab8f0e4b..c31c64683 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_0.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_0.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_1.png b/assets/packs/WatchDogs/Anims/SKULL/frame_1.png index 4449f9cc3..159107d56 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_1.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_1.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_10.png b/assets/packs/WatchDogs/Anims/SKULL/frame_10.png index fda4a43fd..6c9255d31 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_10.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_10.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_11.png b/assets/packs/WatchDogs/Anims/SKULL/frame_11.png index 52be57e77..29257e9f7 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_11.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_11.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_12.png b/assets/packs/WatchDogs/Anims/SKULL/frame_12.png index e14579b85..04f51292f 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_12.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_12.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_13.png b/assets/packs/WatchDogs/Anims/SKULL/frame_13.png index cf7f45963..058d6b5de 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_13.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_13.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_14.png b/assets/packs/WatchDogs/Anims/SKULL/frame_14.png index 73dee0d3d..4561a8f47 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_14.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_14.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_15.png b/assets/packs/WatchDogs/Anims/SKULL/frame_15.png index b08a68f51..ad4c66725 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_15.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_15.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_16.png b/assets/packs/WatchDogs/Anims/SKULL/frame_16.png index 1f005ee27..e0e8e8a2a 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_16.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_16.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_17.png b/assets/packs/WatchDogs/Anims/SKULL/frame_17.png index 057ad3a59..224515d97 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_17.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_17.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_18.png b/assets/packs/WatchDogs/Anims/SKULL/frame_18.png index b2fe331bf..59fc1c106 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_18.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_18.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_19.png b/assets/packs/WatchDogs/Anims/SKULL/frame_19.png index cdf1601d3..aa35b84f5 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_19.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_19.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_2.png b/assets/packs/WatchDogs/Anims/SKULL/frame_2.png index 6d647bc82..76a16c6cf 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_2.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_2.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_20.png b/assets/packs/WatchDogs/Anims/SKULL/frame_20.png index 7cf04e830..158bb2045 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_20.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_20.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_21.png b/assets/packs/WatchDogs/Anims/SKULL/frame_21.png index e5e747ee9..4ffe27fa8 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_21.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_21.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_22.png b/assets/packs/WatchDogs/Anims/SKULL/frame_22.png index a48d68767..35e63c1a3 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_22.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_22.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_23.png b/assets/packs/WatchDogs/Anims/SKULL/frame_23.png index 6f3040f19..dbba6a7ee 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_23.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_23.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_24.png b/assets/packs/WatchDogs/Anims/SKULL/frame_24.png index c1cb28c3d..e265e9c98 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_24.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_24.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_25.png b/assets/packs/WatchDogs/Anims/SKULL/frame_25.png index cda5ab4b5..8fdd941a4 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_25.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_25.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_26.png b/assets/packs/WatchDogs/Anims/SKULL/frame_26.png index a6d932c75..f8933d185 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_26.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_26.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_3.png b/assets/packs/WatchDogs/Anims/SKULL/frame_3.png index 569095f23..f33bdac1e 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_3.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_3.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_4.png b/assets/packs/WatchDogs/Anims/SKULL/frame_4.png index ccef8cefc..7f7abd446 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_4.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_4.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_5.png b/assets/packs/WatchDogs/Anims/SKULL/frame_5.png index 5281fc38f..6620fe99f 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_5.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_5.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_6.png b/assets/packs/WatchDogs/Anims/SKULL/frame_6.png index f89551530..a7438e44e 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_6.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_6.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_7.png b/assets/packs/WatchDogs/Anims/SKULL/frame_7.png index ef696f467..0ab216113 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_7.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_7.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_8.png b/assets/packs/WatchDogs/Anims/SKULL/frame_8.png index 90579348a..57aa15f97 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_8.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_8.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL/frame_9.png b/assets/packs/WatchDogs/Anims/SKULL/frame_9.png index 389793bae..7a8a0b0e7 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL/frame_9.png and b/assets/packs/WatchDogs/Anims/SKULL/frame_9.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_0.png b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_0.png index da0bbeb09..1055d1b43 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_0.png and b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_0.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_1.png b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_1.png index 1b992e98e..32fdab109 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_1.png and b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_1.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_10.png b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_10.png index ba1662e21..6b63aeea5 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_10.png and b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_10.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_11.png b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_11.png index 01726538f..f82c98bfd 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_11.png and b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_11.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_12.png b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_12.png index e2adba2be..2b21eec71 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_12.png and b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_12.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_13.png b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_13.png index 5e8de9e3b..da3380079 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_13.png and b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_13.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_14.png b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_14.png index 76ca1d520..ec9984556 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_14.png and b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_14.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_15.png b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_15.png index e215498e1..e539b44fc 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_15.png and b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_15.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_16.png b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_16.png index 0971331c9..b81641cc7 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_16.png and b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_16.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_17.png b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_17.png index 1dfacb0b1..1c3ed930a 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_17.png and b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_17.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_18.png b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_18.png index 03a9d8992..92b494041 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_18.png and b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_18.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_2.png b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_2.png index f45528f3e..0ff490abe 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_2.png and b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_2.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_3.png b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_3.png index c03ca4ed6..68b339f82 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_3.png and b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_3.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_4.png b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_4.png index 83458fdeb..4fa52fafc 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_4.png and b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_4.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_5.png b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_5.png index 3ab218c47..943fbf1cd 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_5.png and b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_5.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_6.png b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_6.png index 5c9d22b81..062068c64 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_6.png and b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_6.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_7.png b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_7.png index 45bc0c49c..866ae0bb9 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_7.png and b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_7.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_8.png b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_8.png index a172a9292..ae78f135a 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_8.png and b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_8.png differ diff --git a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_9.png b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_9.png index b9e160420..7aef57db1 100644 Binary files a/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_9.png and b/assets/packs/WatchDogs/Anims/SKULL_SPIN/frame_9.png differ diff --git a/assets/packs/WatchDogs/Anims/SPIRAL/frame_0.png b/assets/packs/WatchDogs/Anims/SPIRAL/frame_0.png index c06c86826..32be6dd89 100644 Binary files a/assets/packs/WatchDogs/Anims/SPIRAL/frame_0.png and b/assets/packs/WatchDogs/Anims/SPIRAL/frame_0.png differ diff --git a/assets/packs/WatchDogs/Anims/SPIRAL/frame_1.png b/assets/packs/WatchDogs/Anims/SPIRAL/frame_1.png index 4310dabbc..d3e08b7fd 100644 Binary files a/assets/packs/WatchDogs/Anims/SPIRAL/frame_1.png and b/assets/packs/WatchDogs/Anims/SPIRAL/frame_1.png differ diff --git a/assets/packs/WatchDogs/Anims/SPIRAL/frame_10.png b/assets/packs/WatchDogs/Anims/SPIRAL/frame_10.png index abc935db1..d9f19bdce 100644 Binary files a/assets/packs/WatchDogs/Anims/SPIRAL/frame_10.png and b/assets/packs/WatchDogs/Anims/SPIRAL/frame_10.png differ diff --git a/assets/packs/WatchDogs/Anims/SPIRAL/frame_11.png b/assets/packs/WatchDogs/Anims/SPIRAL/frame_11.png index 6a868594f..c4463e062 100644 Binary files a/assets/packs/WatchDogs/Anims/SPIRAL/frame_11.png and b/assets/packs/WatchDogs/Anims/SPIRAL/frame_11.png differ diff --git a/assets/packs/WatchDogs/Anims/SPIRAL/frame_12.png b/assets/packs/WatchDogs/Anims/SPIRAL/frame_12.png index df2e2b675..aff220aee 100644 Binary files a/assets/packs/WatchDogs/Anims/SPIRAL/frame_12.png and b/assets/packs/WatchDogs/Anims/SPIRAL/frame_12.png differ diff --git a/assets/packs/WatchDogs/Anims/SPIRAL/frame_13.png b/assets/packs/WatchDogs/Anims/SPIRAL/frame_13.png index 169f590ec..5129fd169 100644 Binary files a/assets/packs/WatchDogs/Anims/SPIRAL/frame_13.png and b/assets/packs/WatchDogs/Anims/SPIRAL/frame_13.png differ diff --git a/assets/packs/WatchDogs/Anims/SPIRAL/frame_14.png b/assets/packs/WatchDogs/Anims/SPIRAL/frame_14.png index d1967edb6..b7cac981a 100644 Binary files a/assets/packs/WatchDogs/Anims/SPIRAL/frame_14.png and b/assets/packs/WatchDogs/Anims/SPIRAL/frame_14.png differ diff --git a/assets/packs/WatchDogs/Anims/SPIRAL/frame_15.png b/assets/packs/WatchDogs/Anims/SPIRAL/frame_15.png index 41c8ef76b..89d6e1c78 100644 Binary files a/assets/packs/WatchDogs/Anims/SPIRAL/frame_15.png and b/assets/packs/WatchDogs/Anims/SPIRAL/frame_15.png differ diff --git a/assets/packs/WatchDogs/Anims/SPIRAL/frame_16.png b/assets/packs/WatchDogs/Anims/SPIRAL/frame_16.png index 1a749804b..ff2252dd0 100644 Binary files a/assets/packs/WatchDogs/Anims/SPIRAL/frame_16.png and b/assets/packs/WatchDogs/Anims/SPIRAL/frame_16.png differ diff --git a/assets/packs/WatchDogs/Anims/SPIRAL/frame_17.png b/assets/packs/WatchDogs/Anims/SPIRAL/frame_17.png index 53b713bb6..231205846 100644 Binary files a/assets/packs/WatchDogs/Anims/SPIRAL/frame_17.png and b/assets/packs/WatchDogs/Anims/SPIRAL/frame_17.png differ diff --git a/assets/packs/WatchDogs/Anims/SPIRAL/frame_18.png b/assets/packs/WatchDogs/Anims/SPIRAL/frame_18.png index 57e6ce75b..776e28d02 100644 Binary files a/assets/packs/WatchDogs/Anims/SPIRAL/frame_18.png and b/assets/packs/WatchDogs/Anims/SPIRAL/frame_18.png differ diff --git a/assets/packs/WatchDogs/Anims/SPIRAL/frame_19.png b/assets/packs/WatchDogs/Anims/SPIRAL/frame_19.png index e65d8b0fa..a2bb03dce 100644 Binary files a/assets/packs/WatchDogs/Anims/SPIRAL/frame_19.png and b/assets/packs/WatchDogs/Anims/SPIRAL/frame_19.png differ diff --git a/assets/packs/WatchDogs/Anims/SPIRAL/frame_2.png b/assets/packs/WatchDogs/Anims/SPIRAL/frame_2.png index 1a4fc630b..034ac2634 100644 Binary files a/assets/packs/WatchDogs/Anims/SPIRAL/frame_2.png and b/assets/packs/WatchDogs/Anims/SPIRAL/frame_2.png differ diff --git a/assets/packs/WatchDogs/Anims/SPIRAL/frame_20.png b/assets/packs/WatchDogs/Anims/SPIRAL/frame_20.png index a8c05339a..38a42f563 100644 Binary files a/assets/packs/WatchDogs/Anims/SPIRAL/frame_20.png and b/assets/packs/WatchDogs/Anims/SPIRAL/frame_20.png differ diff --git a/assets/packs/WatchDogs/Anims/SPIRAL/frame_21.png b/assets/packs/WatchDogs/Anims/SPIRAL/frame_21.png index 620f48cee..cb2da59f0 100644 Binary files a/assets/packs/WatchDogs/Anims/SPIRAL/frame_21.png and b/assets/packs/WatchDogs/Anims/SPIRAL/frame_21.png differ diff --git a/assets/packs/WatchDogs/Anims/SPIRAL/frame_22.png b/assets/packs/WatchDogs/Anims/SPIRAL/frame_22.png index 2074676c2..51b6f776a 100644 Binary files a/assets/packs/WatchDogs/Anims/SPIRAL/frame_22.png and b/assets/packs/WatchDogs/Anims/SPIRAL/frame_22.png differ diff --git a/assets/packs/WatchDogs/Anims/SPIRAL/frame_23.png b/assets/packs/WatchDogs/Anims/SPIRAL/frame_23.png index 85ebcc35d..727baed95 100644 Binary files a/assets/packs/WatchDogs/Anims/SPIRAL/frame_23.png and b/assets/packs/WatchDogs/Anims/SPIRAL/frame_23.png differ diff --git a/assets/packs/WatchDogs/Anims/SPIRAL/frame_3.png b/assets/packs/WatchDogs/Anims/SPIRAL/frame_3.png index 0ebb5c7be..16f7748d7 100644 Binary files a/assets/packs/WatchDogs/Anims/SPIRAL/frame_3.png and b/assets/packs/WatchDogs/Anims/SPIRAL/frame_3.png differ diff --git a/assets/packs/WatchDogs/Anims/SPIRAL/frame_4.png b/assets/packs/WatchDogs/Anims/SPIRAL/frame_4.png index 2e0f8cec6..638029b00 100644 Binary files a/assets/packs/WatchDogs/Anims/SPIRAL/frame_4.png and b/assets/packs/WatchDogs/Anims/SPIRAL/frame_4.png differ diff --git a/assets/packs/WatchDogs/Anims/SPIRAL/frame_5.png b/assets/packs/WatchDogs/Anims/SPIRAL/frame_5.png index 6b5bb888a..be8499688 100644 Binary files a/assets/packs/WatchDogs/Anims/SPIRAL/frame_5.png and b/assets/packs/WatchDogs/Anims/SPIRAL/frame_5.png differ diff --git a/assets/packs/WatchDogs/Anims/SPIRAL/frame_6.png b/assets/packs/WatchDogs/Anims/SPIRAL/frame_6.png index d3f3ed448..d8c4b5019 100644 Binary files a/assets/packs/WatchDogs/Anims/SPIRAL/frame_6.png and b/assets/packs/WatchDogs/Anims/SPIRAL/frame_6.png differ diff --git a/assets/packs/WatchDogs/Anims/SPIRAL/frame_7.png b/assets/packs/WatchDogs/Anims/SPIRAL/frame_7.png index f4d15610d..6fc824dc2 100644 Binary files a/assets/packs/WatchDogs/Anims/SPIRAL/frame_7.png and b/assets/packs/WatchDogs/Anims/SPIRAL/frame_7.png differ diff --git a/assets/packs/WatchDogs/Anims/SPIRAL/frame_8.png b/assets/packs/WatchDogs/Anims/SPIRAL/frame_8.png index cb6965801..52aa2089c 100644 Binary files a/assets/packs/WatchDogs/Anims/SPIRAL/frame_8.png and b/assets/packs/WatchDogs/Anims/SPIRAL/frame_8.png differ diff --git a/assets/packs/WatchDogs/Anims/SPIRAL/frame_9.png b/assets/packs/WatchDogs/Anims/SPIRAL/frame_9.png index 9415c239d..568cf5f17 100644 Binary files a/assets/packs/WatchDogs/Anims/SPIRAL/frame_9.png and b/assets/packs/WatchDogs/Anims/SPIRAL/frame_9.png differ diff --git a/assets/packs/WatchDogs/Icons/Dolphin/DolphinSuccess_91x55.png b/assets/packs/WatchDogs/Icons/Dolphin/DolphinSuccess_91x55.png index 8954004e0..7a0bc9a85 100644 Binary files a/assets/packs/WatchDogs/Icons/Dolphin/DolphinSuccess_91x55.png and b/assets/packs/WatchDogs/Icons/Dolphin/DolphinSuccess_91x55.png differ diff --git a/assets/packs/WatchDogs/Icons/NFC/NFC_dolphin_emulation_51x64.png b/assets/packs/WatchDogs/Icons/NFC/NFC_dolphin_emulation_51x64.png index 7df750e84..b5b0ba6fa 100644 Binary files a/assets/packs/WatchDogs/Icons/NFC/NFC_dolphin_emulation_51x64.png and b/assets/packs/WatchDogs/Icons/NFC/NFC_dolphin_emulation_51x64.png differ diff --git a/assets/packs/WatchDogs/Icons/Passport/passport_128x64.png b/assets/packs/WatchDogs/Icons/Passport/passport_128x64.png index acfc53779..8694398c4 100644 Binary files a/assets/packs/WatchDogs/Icons/Passport/passport_128x64.png and b/assets/packs/WatchDogs/Icons/Passport/passport_128x64.png differ diff --git a/assets/packs/WatchDogs/Icons/Passport/passport_bad_46x49.png b/assets/packs/WatchDogs/Icons/Passport/passport_bad_46x49.png index 7c9e758cb..b5a5e2bf4 100644 Binary files a/assets/packs/WatchDogs/Icons/Passport/passport_bad_46x49.png and b/assets/packs/WatchDogs/Icons/Passport/passport_bad_46x49.png differ diff --git a/assets/packs/WatchDogs/Icons/Passport/passport_happy_46x49.png b/assets/packs/WatchDogs/Icons/Passport/passport_happy_46x49.png index 9001675d0..4f5037528 100644 Binary files a/assets/packs/WatchDogs/Icons/Passport/passport_happy_46x49.png and b/assets/packs/WatchDogs/Icons/Passport/passport_happy_46x49.png differ diff --git a/assets/packs/WatchDogs/Icons/Passport/passport_okay_46x49.png b/assets/packs/WatchDogs/Icons/Passport/passport_okay_46x49.png index efcba2b64..63677f2f4 100644 Binary files a/assets/packs/WatchDogs/Icons/Passport/passport_okay_46x49.png and b/assets/packs/WatchDogs/Icons/Passport/passport_okay_46x49.png differ diff --git a/assets/packs/WatchDogs/Icons/RFID/RFIDDolphinReceive_97x61.png b/assets/packs/WatchDogs/Icons/RFID/RFIDDolphinReceive_97x61.png index 7e25d8e20..54c6c3ba7 100644 Binary files a/assets/packs/WatchDogs/Icons/RFID/RFIDDolphinReceive_97x61.png and b/assets/packs/WatchDogs/Icons/RFID/RFIDDolphinReceive_97x61.png differ diff --git a/assets/packs/WatchDogs/Icons/RFID/RFIDDolphinSend_97x61.png b/assets/packs/WatchDogs/Icons/RFID/RFIDDolphinSend_97x61.png index 0639f4996..54c6c3ba7 100644 Binary files a/assets/packs/WatchDogs/Icons/RFID/RFIDDolphinSend_97x61.png and b/assets/packs/WatchDogs/Icons/RFID/RFIDDolphinSend_97x61.png differ diff --git a/assets/packs/WatchDogs/Icons/SubGhz/Fishing_123x52.png b/assets/packs/WatchDogs/Icons/SubGhz/Fishing_123x52.png index fd6762e65..e6aca21ad 100644 Binary files a/assets/packs/WatchDogs/Icons/SubGhz/Fishing_123x52.png and b/assets/packs/WatchDogs/Icons/SubGhz/Fishing_123x52.png differ diff --git a/assets/packs/WatchDogs/Icons/SubGhz/Scanning_123x52.png b/assets/packs/WatchDogs/Icons/SubGhz/Scanning_123x52.png index fd6762e65..e6aca21ad 100644 Binary files a/assets/packs/WatchDogs/Icons/SubGhz/Scanning_123x52.png and b/assets/packs/WatchDogs/Icons/SubGhz/Scanning_123x52.png differ diff --git a/assets/slideshow/first_start/frame_00.png b/assets/slideshow/first_start/frame_00.png index 67f23bd31..51e8f3bbf 100644 Binary files a/assets/slideshow/first_start/frame_00.png and b/assets/slideshow/first_start/frame_00.png differ diff --git a/assets/slideshow/first_start/frame_01.png b/assets/slideshow/first_start/frame_01.png index 5ac995c39..21c8bb319 100644 Binary files a/assets/slideshow/first_start/frame_01.png and b/assets/slideshow/first_start/frame_01.png differ diff --git a/assets/slideshow/first_start/frame_02.png b/assets/slideshow/first_start/frame_02.png index adff6af66..01f58736e 100644 Binary files a/assets/slideshow/first_start/frame_02.png and b/assets/slideshow/first_start/frame_02.png differ diff --git a/assets/slideshow/first_start/frame_03.png b/assets/slideshow/first_start/frame_03.png index bd6ae73f7..898d59f95 100644 Binary files a/assets/slideshow/first_start/frame_03.png and b/assets/slideshow/first_start/frame_03.png differ diff --git a/assets/slideshow/first_start/frame_04.png b/assets/slideshow/first_start/frame_04.png index 59f62dcc7..1d187554a 100644 Binary files a/assets/slideshow/first_start/frame_04.png and b/assets/slideshow/first_start/frame_04.png differ diff --git a/assets/slideshow/first_start/frame_05.png b/assets/slideshow/first_start/frame_05.png index 3682c6d0c..64b34b05b 100644 Binary files a/assets/slideshow/first_start/frame_05.png and b/assets/slideshow/first_start/frame_05.png differ diff --git a/assets/slideshow/firstboot/frame_00.png b/assets/slideshow/firstboot/frame_00.png index f5d7475f7..1c4aff150 100644 Binary files a/assets/slideshow/firstboot/frame_00.png and b/assets/slideshow/firstboot/frame_00.png differ diff --git a/assets/slideshow/firstboot/frame_01.png b/assets/slideshow/firstboot/frame_01.png index 6bfe937ee..f667a0d72 100644 Binary files a/assets/slideshow/firstboot/frame_01.png and b/assets/slideshow/firstboot/frame_01.png differ diff --git a/assets/slideshow/firstboot/frame_02.png b/assets/slideshow/firstboot/frame_02.png index dcbe46f8f..3363df414 100644 Binary files a/assets/slideshow/firstboot/frame_02.png and b/assets/slideshow/firstboot/frame_02.png differ diff --git a/assets/slideshow/firstboot/frame_03.png b/assets/slideshow/firstboot/frame_03.png index 5b91bd387..835730863 100644 Binary files a/assets/slideshow/firstboot/frame_03.png and b/assets/slideshow/firstboot/frame_03.png differ diff --git a/assets/slideshow/firstboot/frame_04.png b/assets/slideshow/firstboot/frame_04.png index 770f29bf0..6f33a02ad 100644 Binary files a/assets/slideshow/firstboot/frame_04.png and b/assets/slideshow/firstboot/frame_04.png differ diff --git a/assets/slideshow/firstboot/frame_05.png b/assets/slideshow/firstboot/frame_05.png index fdb1604ae..f8dbaaf1d 100644 Binary files a/assets/slideshow/firstboot/frame_05.png and b/assets/slideshow/firstboot/frame_05.png differ diff --git a/assets/slideshow/firstboot/frame_06.png b/assets/slideshow/firstboot/frame_06.png index 76ae4cdda..36131a255 100644 Binary files a/assets/slideshow/firstboot/frame_06.png and b/assets/slideshow/firstboot/frame_06.png differ diff --git a/assets/slideshow/update_default/frame_00.png b/assets/slideshow/update_default/frame_00.png index cdb9c3394..32a22f84b 100644 Binary files a/assets/slideshow/update_default/frame_00.png and b/assets/slideshow/update_default/frame_00.png differ diff --git a/documentation/doxygen/Doxyfile.cfg b/documentation/doxygen/Doxyfile.cfg index 2596d161f..a7838163b 100644 --- a/documentation/doxygen/Doxyfile.cfg +++ b/documentation/doxygen/Doxyfile.cfg @@ -1023,7 +1023,6 @@ RECURSIVE = YES EXCLUDE = $(DOXY_SRC_ROOT)/lib/mlib \ $(DOXY_SRC_ROOT)/lib/STM32CubeWB \ - $(DOXY_SRC_ROOT)/lib/littlefs \ $(DOXY_SRC_ROOT)/lib/nanopb \ $(DOXY_SRC_ROOT)/assets/protobuf \ $(DOXY_SRC_ROOT)/lib/libusb_stm32 \ diff --git a/documentation/fbt.md b/documentation/fbt.md index a8759f8eb..4009822f8 100644 --- a/documentation/fbt.md +++ b/documentation/fbt.md @@ -101,6 +101,8 @@ Currently `fbt` supports the default language server (`cpptools`) and `clangd`. - `get_stlink` - output serial numbers for attached STLink probes. Used for specifying an adapter with `SWD_TRANSPORT_SERIAL=...`. - `lint`, `format` - run `clang-format` on the C source code to check and reformat it according to the `.clang-format` specs. Supports `ARGS="..."` to pass extra arguments to clang-format. - `lint_py`, `format_py` - run [black](https://black.readthedocs.io/en/stable/index.html) on the Python source code, build system files & application manifests. Supports `ARGS="..."` to pass extra arguments to black. +- `lint_img`, `format_img` - check the image assets for errors and format them. Enforces color depth and strips metadata. +- `lint_all`, `format_all` - run all linters and formatters. - `firmware_pvs` - generate a PVS Studio report for the firmware. Requires PVS Studio to be available on your system's `PATH`. - `doxygen` - generate Doxygen documentation for the firmware. `doxy` target also opens web browser to view the generated documentation. - `cli` - start a Flipper CLI session over USB. diff --git a/furi/core/check.h b/furi/core/check.h index 199b8b40f..f64bf17d4 100644 --- a/furi/core/check.h +++ b/furi/core/check.h @@ -21,9 +21,9 @@ extern "C" { #endif // When enabled will use file paths instead of "furi_check failed" -// #if !defined(FURI_RAM_EXEC) && !defined(FURI_DEBUG) -// #define __FURI_TRACE -// #endif +#if !defined(FURI_RAM_EXEC) && !defined(FURI_DEBUG) +#define __FURI_TRACE +#endif // Flags instead of pointers will save ~4 bytes on furi_assert and furi_check calls. #ifndef __FURI_TRACE diff --git a/furi/core/event_loop.c b/furi/core/event_loop.c index 26401c84b..2a6cd51d3 100644 --- a/furi/core/event_loop.c +++ b/furi/core/event_loop.c @@ -1,5 +1,4 @@ #include "event_loop_i.h" -#include "message_queue_i.h" #include "log.h" #include "check.h" @@ -22,13 +21,17 @@ static FuriEventLoopItem* furi_event_loop_item_alloc( static void furi_event_loop_item_free(FuriEventLoopItem* instance); +static void furi_event_loop_item_free_later(FuriEventLoopItem* instance); + static void furi_event_loop_item_set_callback( FuriEventLoopItem* instance, - FuriEventLoopMessageQueueCallback callback, + FuriEventLoopEventCallback callback, void* callback_context); static void furi_event_loop_item_notify(FuriEventLoopItem* instance); +static bool furi_event_loop_item_is_waiting(FuriEventLoopItem* instance); + static void furi_event_loop_process_pending_callbacks(FuriEventLoop* instance) { for(; !PendingQueue_empty_p(instance->pending_queue); PendingQueue_pop_back(NULL, instance->pending_queue)) { @@ -37,6 +40,21 @@ static void furi_event_loop_process_pending_callbacks(FuriEventLoop* instance) { } } +static bool furi_event_loop_signal_callback(uint32_t signal, void* arg, void* context) { + furi_assert(context); + FuriEventLoop* instance = context; + UNUSED(arg); + + switch(signal) { + case FuriSignalExit: + furi_event_loop_stop(instance); + return true; + // Room for possible other standard signal handlers + default: + return false; + } +} + /* * Main public API */ @@ -67,6 +85,7 @@ void furi_event_loop_free(FuriEventLoop* instance) { furi_event_loop_process_timer_queue(instance); furi_check(TimerList_empty_p(instance->timer_list)); + furi_check(WaitingList_empty_p(instance->waiting_list)); FuriEventLoopTree_clear(instance->tree); PendingQueue_clear(instance->pending_queue); @@ -81,21 +100,81 @@ void furi_event_loop_free(FuriEventLoop* instance) { free(instance); } -static FuriEventLoopProcessStatus - furi_event_loop_poll_process_event(FuriEventLoop* instance, FuriEventLoopItem* item) { - UNUSED(instance); - +static inline FuriEventLoopProcessStatus + furi_event_loop_poll_process_level_event(FuriEventLoopItem* item) { if(!item->contract->get_level(item->object, item->event)) { return FuriEventLoopProcessStatusComplete; - } - - if(item->callback(item->object, item->callback_context)) { + } else if(item->callback(item->object, item->callback_context)) { return FuriEventLoopProcessStatusIncomplete; } else { return FuriEventLoopProcessStatusAgain; } } +static inline FuriEventLoopProcessStatus + furi_event_loop_poll_process_edge_event(FuriEventLoopItem* item) { + if(item->callback(item->object, item->callback_context)) { + return FuriEventLoopProcessStatusComplete; + } else { + return FuriEventLoopProcessStatusAgain; + } +} + +static inline FuriEventLoopProcessStatus + furi_event_loop_poll_process_event(FuriEventLoop* instance, FuriEventLoopItem* item) { + FuriEventLoopProcessStatus status; + if(item->event & FuriEventLoopEventFlagOnce) { + furi_event_loop_unsubscribe(instance, item->object); + } + + if(item->event & FuriEventLoopEventFlagEdge) { + status = furi_event_loop_poll_process_edge_event(item); + } else { + status = furi_event_loop_poll_process_level_event(item); + } + + if(item->owner == NULL) { + status = FuriEventLoopProcessStatusFreeLater; + } + + return status; +} + +static void furi_event_loop_process_waiting_list(FuriEventLoop* instance) { + FuriEventLoopItem* item = NULL; + + FURI_CRITICAL_ENTER(); + + if(!WaitingList_empty_p(instance->waiting_list)) { + item = WaitingList_pop_front(instance->waiting_list); + WaitingList_init_field(item); + } + + FURI_CRITICAL_EXIT(); + + if(!item) return; + + while(true) { + FuriEventLoopProcessStatus ret = furi_event_loop_poll_process_event(instance, item); + + if(ret == FuriEventLoopProcessStatusComplete) { + // Event processing complete, break from loop + break; + } else if(ret == FuriEventLoopProcessStatusIncomplete) { + // Event processing incomplete more processing needed + } else if(ret == FuriEventLoopProcessStatusAgain) { //-V547 + furi_event_loop_item_notify(item); + break; + // Unsubscribed from inside the callback, delete item + } else if(ret == FuriEventLoopProcessStatusFreeLater) { //-V547 + furi_event_loop_item_free(item); + break; + } else { + furi_crash(); + } + } +} + static void furi_event_loop_restore_flags(FuriEventLoop* instance, uint32_t flags) { if(flags) { xTaskNotifyIndexed( @@ -107,10 +186,13 @@ void furi_event_loop_run(FuriEventLoop* instance) { furi_check(instance); furi_check(instance->thread_id == furi_thread_get_current_id()); - furi_event_loop_init_tick(instance); + // Set the default signal callback if none was previously set + if(furi_thread_get_signal_callback(instance->thread_id) == NULL) { + furi_thread_set_signal_callback( + instance->thread_id, furi_event_loop_signal_callback, instance); + } - furi_thread_set_signal_callback( - instance->thread_id, furi_event_loop_signal_callback, instance); + furi_event_loop_init_tick(instance); while(true) { instance->state = FuriEventLoopStateIdle; @@ -131,34 +213,7 @@ void furi_event_loop_run(FuriEventLoop* instance) { break; } else if(flags & FuriEventLoopFlagEvent) { - FuriEventLoopItem* item = NULL; - FURI_CRITICAL_ENTER(); - - if(!WaitingList_empty_p(instance->waiting_list)) { - item = WaitingList_pop_front(instance->waiting_list); - WaitingList_init_field(item); - } - - FURI_CRITICAL_EXIT(); - - if(item) { - while(true) { - FuriEventLoopProcessStatus ret = - furi_event_loop_poll_process_event(instance, item); - if(ret == FuriEventLoopProcessStatusComplete) { - // Event processing complete, break from loop - break; - } else if(ret == FuriEventLoopProcessStatusIncomplete) { - // Event processing incomplete more processing needed - } else if(ret == FuriEventLoopProcessStatusAgain) { //-V547 - furi_event_loop_item_notify(item); - break; - } else { - furi_crash(); - } - } - } - + furi_event_loop_process_waiting_list(instance); furi_event_loop_restore_flags(instance, flags & ~FuriEventLoopFlagEvent); } else if(flags & FuriEventLoopFlagTimer) { @@ -177,7 +232,10 @@ void furi_event_loop_run(FuriEventLoop* instance) { } } - furi_thread_set_signal_callback(instance->thread_id, NULL, NULL); + // Disable the default signal callback + if(furi_thread_get_signal_callback(instance->thread_id) == furi_event_loop_signal_callback) { + furi_thread_set_signal_callback(instance->thread_id, NULL, NULL); + } } void furi_event_loop_stop(FuriEventLoop* instance) { @@ -211,87 +269,150 @@ void furi_event_loop_pend_callback( } /* - * Message queue API + * Private generic susbscription API */ -void furi_event_loop_message_queue_subscribe( +static void furi_event_loop_object_subscribe( FuriEventLoop* instance, - FuriMessageQueue* message_queue, + FuriEventLoopObject* object, + const FuriEventLoopContract* contract, FuriEventLoopEvent event, - FuriEventLoopMessageQueueCallback callback, + FuriEventLoopEventCallback callback, void* context) { furi_check(instance); furi_check(instance->thread_id == furi_thread_get_current_id()); - furi_check(instance->state == FuriEventLoopStateStopped); - furi_check(message_queue); + furi_check(object); + furi_assert(contract); + furi_check(callback); FURI_CRITICAL_ENTER(); - furi_check(FuriEventLoopTree_get(instance->tree, message_queue) == NULL); + furi_check(FuriEventLoopTree_get(instance->tree, object) == NULL); // Allocate and setup item - FuriEventLoopItem* item = furi_event_loop_item_alloc( - instance, &furi_message_queue_event_loop_contract, message_queue, event); + FuriEventLoopItem* item = furi_event_loop_item_alloc(instance, contract, object, event); furi_event_loop_item_set_callback(item, callback, context); - FuriEventLoopTree_set_at(instance->tree, message_queue, item); + FuriEventLoopTree_set_at(instance->tree, object, item); - FuriEventLoopLink* link = item->contract->get_link(message_queue); + FuriEventLoopLink* link = item->contract->get_link(object); + FuriEventLoopEvent event_noflags = item->event & FuriEventLoopEventMask; - if(item->event == FuriEventLoopEventIn) { + if(event_noflags == FuriEventLoopEventIn) { furi_check(link->item_in == NULL); link->item_in = item; - } else if(item->event == FuriEventLoopEventOut) { + } else if(event_noflags == FuriEventLoopEventOut) { furi_check(link->item_out == NULL); link->item_out = item; } else { furi_crash(); } - if(item->contract->get_level(item->object, item->event)) { - furi_event_loop_item_notify(item); + if(!(item->event & FuriEventLoopEventFlagEdge)) { + if(item->contract->get_level(item->object, event_noflags)) { + furi_event_loop_item_notify(item); + } } FURI_CRITICAL_EXIT(); } -void furi_event_loop_message_queue_unsubscribe( +/** + * Public specialized subscription API + */ + +void furi_event_loop_subscribe_message_queue( FuriEventLoop* instance, - FuriMessageQueue* message_queue) { + FuriMessageQueue* message_queue, + FuriEventLoopEvent event, + FuriEventLoopEventCallback callback, + void* context) { + extern const FuriEventLoopContract furi_message_queue_event_loop_contract; + + furi_event_loop_object_subscribe( + instance, message_queue, &furi_message_queue_event_loop_contract, event, callback, context); +} + +void furi_event_loop_subscribe_stream_buffer( + FuriEventLoop* instance, + FuriStreamBuffer* stream_buffer, + FuriEventLoopEvent event, + FuriEventLoopEventCallback callback, + void* context) { + extern const FuriEventLoopContract furi_stream_buffer_event_loop_contract; + + furi_event_loop_object_subscribe( + instance, stream_buffer, &furi_stream_buffer_event_loop_contract, event, callback, context); +} + +void furi_event_loop_subscribe_semaphore( + FuriEventLoop* instance, + FuriSemaphore* semaphore, + FuriEventLoopEvent event, + FuriEventLoopEventCallback callback, + void* context) { + extern const FuriEventLoopContract furi_semaphore_event_loop_contract; + + furi_event_loop_object_subscribe( + instance, semaphore, &furi_semaphore_event_loop_contract, event, callback, context); +} + +void furi_event_loop_subscribe_mutex( + FuriEventLoop* instance, + FuriMutex* mutex, + FuriEventLoopEvent event, + FuriEventLoopEventCallback callback, + void* context) { + extern const FuriEventLoopContract furi_mutex_event_loop_contract; + + furi_event_loop_object_subscribe( + instance, mutex, &furi_mutex_event_loop_contract, event, callback, context); +} + +/** + * Public generic unsubscription API + */ + +void furi_event_loop_unsubscribe(FuriEventLoop* instance, FuriEventLoopObject* object) { furi_check(instance); - furi_check(instance->state == FuriEventLoopStateStopped); furi_check(instance->thread_id == furi_thread_get_current_id()); FURI_CRITICAL_ENTER(); - FuriEventLoopItem** item_ptr = FuriEventLoopTree_get(instance->tree, message_queue); - furi_check(item_ptr); + FuriEventLoopItem* item = NULL; + furi_check(FuriEventLoopTree_pop_at(&item, instance->tree, object)); - FuriEventLoopItem* item = *item_ptr; furi_check(item); furi_check(item->owner == instance); - FuriEventLoopLink* link = item->contract->get_link(message_queue); + FuriEventLoopLink* link = item->contract->get_link(object); + FuriEventLoopEvent event_noflags = item->event & FuriEventLoopEventMask; - if(item->event == FuriEventLoopEventIn) { + if(event_noflags == FuriEventLoopEventIn) { furi_check(link->item_in == item); link->item_in = NULL; - } else if(item->event == FuriEventLoopEventOut) { + } else if(event_noflags == FuriEventLoopEventOut) { furi_check(link->item_out == item); link->item_out = NULL; } else { furi_crash(); } - furi_event_loop_item_free(item); + if(furi_event_loop_item_is_waiting(item)) { + WaitingList_unlink(item); + } - FuriEventLoopTree_erase(instance->tree, message_queue); + if(instance->state == FuriEventLoopStateProcessing) { + furi_event_loop_item_free_later(item); + } else { + furi_event_loop_item_free(item); + } FURI_CRITICAL_EXIT(); } /* - * Event Loop Item API, used internally + * Private Event Loop Item functions */ static FuriEventLoopItem* furi_event_loop_item_alloc( @@ -316,12 +437,19 @@ static FuriEventLoopItem* furi_event_loop_item_alloc( static void furi_event_loop_item_free(FuriEventLoopItem* instance) { furi_assert(instance); + furi_assert(!furi_event_loop_item_is_waiting(instance)); free(instance); } +static void furi_event_loop_item_free_later(FuriEventLoopItem* instance) { + furi_assert(instance); + furi_assert(!furi_event_loop_item_is_waiting(instance)); + instance->owner = NULL; +} + static void furi_event_loop_item_set_callback( FuriEventLoopItem* instance, - FuriEventLoopMessageQueueCallback callback, + FuriEventLoopEventCallback callback, void* callback_context) { furi_assert(instance); furi_assert(!instance->callback); @@ -335,27 +463,35 @@ static void furi_event_loop_item_notify(FuriEventLoopItem* instance) { FURI_CRITICAL_ENTER(); - if(!instance->WaitingList.prev && !instance->WaitingList.next) { - WaitingList_push_back(instance->owner->waiting_list, instance); + FuriEventLoop* owner = instance->owner; + furi_assert(owner); + + if(!furi_event_loop_item_is_waiting(instance)) { + WaitingList_push_back(owner->waiting_list, instance); } FURI_CRITICAL_EXIT(); xTaskNotifyIndexed( - instance->owner->thread_id, - FURI_EVENT_LOOP_FLAG_NOTIFY_INDEX, - FuriEventLoopFlagEvent, - eSetBits); + owner->thread_id, FURI_EVENT_LOOP_FLAG_NOTIFY_INDEX, FuriEventLoopFlagEvent, eSetBits); } +static bool furi_event_loop_item_is_waiting(FuriEventLoopItem* instance) { + return instance->WaitingList.prev || instance->WaitingList.next; +} + +/* + * Internal event loop link API, used by supported primitives + */ + void furi_event_loop_link_notify(FuriEventLoopLink* instance, FuriEventLoopEvent event) { furi_assert(instance); FURI_CRITICAL_ENTER(); - if(event == FuriEventLoopEventIn) { + if(event & FuriEventLoopEventIn) { if(instance->item_in) furi_event_loop_item_notify(instance->item_in); - } else if(event == FuriEventLoopEventOut) { + } else if(event & FuriEventLoopEventOut) { if(instance->item_out) furi_event_loop_item_notify(instance->item_out); } else { furi_crash(); @@ -363,18 +499,3 @@ void furi_event_loop_link_notify(FuriEventLoopLink* instance, FuriEventLoopEvent FURI_CRITICAL_EXIT(); } - -bool furi_event_loop_signal_callback(uint32_t signal, void* arg, void* context) { - furi_assert(context); - FuriEventLoop* instance = context; - UNUSED(arg); - - switch(signal) { - case FuriSignalExit: - furi_event_loop_stop(instance); - return true; - // Room for possible other standard signal handlers - default: - return false; - } -} diff --git a/furi/core/event_loop.h b/furi/core/event_loop.h index 9ae9f6c4d..af5987101 100644 --- a/furi/core/event_loop.h +++ b/furi/core/event_loop.h @@ -20,10 +20,83 @@ extern "C" { #endif -/** Event Loop events */ +/** + * @brief Enumeration of event types, flags and masks. + * + * Only one event direction (In or Out) can be used per subscription. + * An object can have no more than one subscription for each direction. + * + * Additional flags that modify the behaviour can be + * set using the bitwise OR operation (see flag description). + */ typedef enum { - FuriEventLoopEventOut, /**< On departure: item was retrieved from container, flag reset, etc... */ - FuriEventLoopEventIn, /**< On arrival: item was inserted into container, flag set, etc... */ + /** + * @brief Subscribe to In events. + * + * In events occur on the following conditions: + * - One or more items were inserted into a FuriMessageQueue, + * - Enough data has been written to a FuriStreamBuffer, + * - A FuriSemaphore has been released at least once, + * - A FuriMutex has been released. + */ + FuriEventLoopEventIn = 0x00000001U, + /** + * @brief Subscribe to Out events. + * + * Out events occur on the following conditions: + * - One or more items were removed from a FuriMessageQueue, + * - Any amount of data has been read out of a FuriStreamBuffer, + * - A FuriSemaphore has been acquired at least once, + * - A FuriMutex has been acquired. + */ + FuriEventLoopEventOut = 0x00000002U, + /** + * @brief Special value containing the event direction bits, used internally. + */ + FuriEventLoopEventMask = 0x00000003U, + /** + * @brief Use edge triggered events. + * + * By default, level triggered events are used. A level above zero + * is reported based on the following conditions: + * + * In events: + * - a FuriMessageQueue contains one or more items, + * - a FuriStreamBuffer contains one or more bytes, + * - a FuriSemaphore can be acquired at least once, + * - a FuriMutex can be acquired. + * + * Out events: + * - a FuriMessageQueue has at least one item of free space, + * - a FuriStreamBuffer has at least one byte of free space, + * - a FuriSemaphore has been acquired at least once, + * - a FuriMutex has been acquired. + * + * If this flag is NOT set, the event will be generated repeatedly until + * the level becomes zero (e.g. all items have been removed from + * a FuriMessageQueue in case of the "In" event, etc.) + * + * If this flag IS set, then the above check is skipped and the event + * is generated ONLY when a change occurs, with the event direction + * (In or Out) taken into account. + */ + FuriEventLoopEventFlagEdge = 0x00000004U, + /** + * @brief Automatically unsubscribe from events after one time. + * + * By default, events will be generated each time the specified conditions + * have been met. If this flag IS set, the event subscription will be cancelled + * upon the first occurred event and no further events will be generated. + */ + FuriEventLoopEventFlagOnce = 0x00000008U, + /** + * @brief Special value containing the event flag bits, used internally. + */ + FuriEventLoopEventFlagMask = 0xFFFFFFFCU, + /** + * @brief Special value to force the enum to 32-bit values. + */ + FuriEventLoopEventReserved = UINT32_MAX, } FuriEventLoopEvent; /** Anonymous message queue type */ @@ -115,21 +188,22 @@ void furi_event_loop_pend_callback( void* context); /* - * Message queue related APIs + * Event subscription/notification APIs */ -/** Anonymous message queue type */ -typedef struct FuriMessageQueue FuriMessageQueue; +typedef void FuriEventLoopObject; -/** Callback type for message queue +/** Callback type for event loop events * - * @param queue The queue that triggered event - * @param context The context that was provided on - * furi_event_loop_message_queue_subscribe call + * @param object The object that triggered the event + * @param context The context that was provided upon subscription * * @return true if event was processed, false if we need to delay processing */ -typedef bool (*FuriEventLoopMessageQueueCallback)(FuriMessageQueue* queue, void* context); +typedef bool (*FuriEventLoopEventCallback)(FuriEventLoopObject* object, void* context); + +/** Opaque message queue type */ +typedef struct FuriMessageQueue FuriMessageQueue; /** Subscribe to message queue events * @@ -141,21 +215,79 @@ typedef bool (*FuriEventLoopMessageQueueCallback)(FuriMessageQueue* queue, void* * @param[in] callback The callback to call on event * @param context The context for callback */ -void furi_event_loop_message_queue_subscribe( +void furi_event_loop_subscribe_message_queue( FuriEventLoop* instance, FuriMessageQueue* message_queue, FuriEventLoopEvent event, - FuriEventLoopMessageQueueCallback callback, + FuriEventLoopEventCallback callback, void* context); -/** Unsubscribe from message queue +/** Opaque stream buffer type */ +typedef struct FuriStreamBuffer FuriStreamBuffer; + +/** Subscribe to stream buffer events + * + * @warning you can only have one subscription for one event type. * * @param instance The Event Loop instance - * @param message_queue The message queue + * @param stream_buffer The stream buffer to add + * @param[in] event The Event Loop event to trigger on + * @param[in] callback The callback to call on event + * @param context The context for callback */ -void furi_event_loop_message_queue_unsubscribe( +void furi_event_loop_subscribe_stream_buffer( FuriEventLoop* instance, - FuriMessageQueue* message_queue); + FuriStreamBuffer* stream_buffer, + FuriEventLoopEvent event, + FuriEventLoopEventCallback callback, + void* context); + +/** Opaque semaphore type */ +typedef struct FuriSemaphore FuriSemaphore; + +/** Subscribe to semaphore events + * + * @warning you can only have one subscription for one event type. + * + * @param instance The Event Loop instance + * @param semaphore The semaphore to add + * @param[in] event The Event Loop event to trigger on + * @param[in] callback The callback to call on event + * @param context The context for callback + */ +void furi_event_loop_subscribe_semaphore( + FuriEventLoop* instance, + FuriSemaphore* semaphore, + FuriEventLoopEvent event, + FuriEventLoopEventCallback callback, + void* context); + +/** Opaque mutex type */ +typedef struct FuriMutex FuriMutex; + +/** Subscribe to mutex events + * + * @warning you can only have one subscription for one event type. + * + * @param instance The Event Loop instance + * @param mutex The mutex to add + * @param[in] event The Event Loop event to trigger on + * @param[in] callback The callback to call on event + * @param context The context for callback + */ +void furi_event_loop_subscribe_mutex( + FuriEventLoop* instance, + FuriMutex* mutex, + FuriEventLoopEvent event, + FuriEventLoopEventCallback callback, + void* context); + +/** Unsubscribe from events (common) + * + * @param instance The Event Loop instance + * @param object The object to unsubscribe from + */ +void furi_event_loop_unsubscribe(FuriEventLoop* instance, FuriEventLoopObject* object); #ifdef __cplusplus } diff --git a/furi/core/event_loop_i.h b/furi/core/event_loop_i.h index cd1014867..15efa8f86 100644 --- a/furi/core/event_loop_i.h +++ b/furi/core/event_loop_i.h @@ -16,16 +16,16 @@ struct FuriEventLoopItem { FuriEventLoop* owner; // Tracking item - const FuriEventLoopContract* contract; - void* object; FuriEventLoopEvent event; + FuriEventLoopObject* object; + const FuriEventLoopContract* contract; // Callback and context - FuriEventLoopMessageQueueCallback callback; + FuriEventLoopEventCallback callback; void* callback_context; // Waiting list - ILIST_INTERFACE(WaitingList, struct FuriEventLoopItem); + ILIST_INTERFACE(WaitingList, FuriEventLoopItem); }; ILIST_DEF(WaitingList, FuriEventLoopItem, M_POD_OPLIST) @@ -36,7 +36,7 @@ ILIST_DEF(WaitingList, FuriEventLoopItem, M_POD_OPLIST) BPTREE_DEF2( // NOLINT FuriEventLoopTree, FURI_EVENT_LOOP_TREE_RANK, - void*, /* pointer to object we track */ + FuriEventLoopObject*, /* pointer to object we track */ M_PTR_OPLIST, FuriEventLoopItem*, /* pointer to the FuriEventLoopItem */ M_PTR_OPLIST) @@ -60,6 +60,7 @@ typedef enum { FuriEventLoopProcessStatusComplete, FuriEventLoopProcessStatusIncomplete, FuriEventLoopProcessStatusAgain, + FuriEventLoopProcessStatusFreeLater, } FuriEventLoopProcessStatus; typedef enum { diff --git a/furi/core/event_loop_link_i.h b/furi/core/event_loop_link_i.h index 5c0b144a1..992ca6555 100644 --- a/furi/core/event_loop_link_i.h +++ b/furi/core/event_loop_link_i.h @@ -19,17 +19,16 @@ void furi_event_loop_link_notify(FuriEventLoopLink* instance, FuriEventLoopEvent /* Contract between event loop and an object */ -typedef FuriEventLoopLink* (*FuriEventLoopContractGetLink)(void* object); +typedef FuriEventLoopLink* (*FuriEventLoopContractGetLink)(FuriEventLoopObject* object); -typedef uint32_t (*FuriEventLoopContractGetLevel)(void* object, FuriEventLoopEvent event); +typedef uint32_t ( + *FuriEventLoopContractGetLevel)(FuriEventLoopObject* object, FuriEventLoopEvent event); typedef struct { const FuriEventLoopContractGetLink get_link; const FuriEventLoopContractGetLevel get_level; } FuriEventLoopContract; -bool furi_event_loop_signal_callback(uint32_t signal, void* arg, void* context); - #ifdef __cplusplus } #endif diff --git a/furi/core/message_queue.c b/furi/core/message_queue.c index 3521ceb30..bd0cec021 100644 --- a/furi/core/message_queue.c +++ b/furi/core/message_queue.c @@ -1,4 +1,4 @@ -#include "message_queue_i.h" +#include "message_queue.h" #include #include @@ -6,6 +6,8 @@ #include "kernel.h" #include "check.h" +#include "event_loop_link_i.h" + // Internal FreeRTOS member names #define uxMessagesWaiting uxDummy4[0] #define uxLength uxDummy4[1] @@ -13,10 +15,7 @@ struct FuriMessageQueue { StaticQueue_t container; - - // Event Loop Link FuriEventLoopLink event_loop_link; - uint8_t buffer[]; }; @@ -208,13 +207,14 @@ FuriStatus furi_message_queue_reset(FuriMessageQueue* instance) { return stat; } -static FuriEventLoopLink* furi_message_queue_event_loop_get_link(void* object) { +static FuriEventLoopLink* furi_message_queue_event_loop_get_link(FuriEventLoopObject* object) { FuriMessageQueue* instance = object; furi_assert(instance); return &instance->event_loop_link; } -static uint32_t furi_message_queue_event_loop_get_level(void* object, FuriEventLoopEvent event) { +static uint32_t + furi_message_queue_event_loop_get_level(FuriEventLoopObject* object, FuriEventLoopEvent event) { FuriMessageQueue* instance = object; furi_assert(instance); diff --git a/furi/core/message_queue_i.h b/furi/core/message_queue_i.h deleted file mode 100644 index a88d04131..000000000 --- a/furi/core/message_queue_i.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include "message_queue.h" -#include "event_loop_link_i.h" - -extern const FuriEventLoopContract furi_message_queue_event_loop_contract; diff --git a/furi/core/mutex.c b/furi/core/mutex.c index f59ae83ad..f9848e1ba 100644 --- a/furi/core/mutex.c +++ b/furi/core/mutex.c @@ -1,15 +1,18 @@ #include "mutex.h" -#include "check.h" -#include "common_defines.h" #include #include +#include "check.h" + +#include "event_loop_link_i.h" + // Internal FreeRTOS member names #define ucQueueType ucDummy9 struct FuriMutex { StaticSemaphore_t container; + FuriEventLoopLink event_loop_link; }; // IMPORTANT: container MUST be the FIRST struct member @@ -39,6 +42,10 @@ void furi_mutex_free(FuriMutex* instance) { furi_check(!FURI_IS_IRQ_MODE()); furi_check(instance); + // Event Loop must be disconnected + furi_check(!instance->event_loop_link.item_in); + furi_check(!instance->event_loop_link.item_out); + vSemaphoreDelete((SemaphoreHandle_t)instance); free(instance); } @@ -76,6 +83,10 @@ FuriStatus furi_mutex_acquire(FuriMutex* instance, uint32_t timeout) { furi_crash(); } + if(stat == FuriStatusOk) { + furi_event_loop_link_notify(&instance->event_loop_link, FuriEventLoopEventOut); + } + return stat; } @@ -104,6 +115,10 @@ FuriStatus furi_mutex_release(FuriMutex* instance) { furi_crash(); } + if(stat == FuriStatusOk) { + furi_event_loop_link_notify(&instance->event_loop_link, FuriEventLoopEventIn); + } + return stat; } @@ -122,3 +137,26 @@ FuriThreadId furi_mutex_get_owner(FuriMutex* instance) { return owner; } + +static FuriEventLoopLink* furi_mutex_event_loop_get_link(FuriEventLoopObject* object) { + FuriMutex* instance = object; + furi_assert(instance); + return &instance->event_loop_link; +} + +static uint32_t + furi_mutex_event_loop_get_level(FuriEventLoopObject* object, FuriEventLoopEvent event) { + FuriMutex* instance = object; + furi_assert(instance); + + if(event == FuriEventLoopEventIn || event == FuriEventLoopEventOut) { + return furi_mutex_get_owner(instance) ? 0 : 1; + } else { + furi_crash(); + } +} + +const FuriEventLoopContract furi_mutex_event_loop_contract = { + .get_link = furi_mutex_event_loop_get_link, + .get_level = furi_mutex_event_loop_get_level, +}; diff --git a/furi/core/semaphore.c b/furi/core/semaphore.c index 6413eb65f..850169ad6 100644 --- a/furi/core/semaphore.c +++ b/furi/core/semaphore.c @@ -1,12 +1,20 @@ #include "semaphore.h" -#include "check.h" -#include "common_defines.h" #include #include +#include "check.h" +#include "kernel.h" + +#include "event_loop_link_i.h" + +// Internal FreeRTOS member names +#define uxMessagesWaiting uxDummy4[0] +#define uxLength uxDummy4[1] + struct FuriSemaphore { StaticSemaphore_t container; + FuriEventLoopLink event_loop_link; }; // IMPORTANT: container MUST be the FIRST struct member @@ -40,6 +48,10 @@ void furi_semaphore_free(FuriSemaphore* instance) { furi_check(instance); furi_check(!FURI_IS_IRQ_MODE()); + // Event Loop must be disconnected + furi_check(!instance->event_loop_link.item_in); + furi_check(!instance->event_loop_link.item_out); + vSemaphoreDelete((SemaphoreHandle_t)instance); free(instance); } @@ -76,6 +88,10 @@ FuriStatus furi_semaphore_acquire(FuriSemaphore* instance, uint32_t timeout) { } } + if(stat == FuriStatusOk) { + furi_event_loop_link_notify(&instance->event_loop_link, FuriEventLoopEventOut); + } + return stat; } @@ -103,6 +119,10 @@ FuriStatus furi_semaphore_release(FuriSemaphore* instance) { } } + if(stat == FuriStatusOk) { + furi_event_loop_link_notify(&instance->event_loop_link, FuriEventLoopEventIn); + } + return stat; } @@ -120,3 +140,46 @@ uint32_t furi_semaphore_get_count(FuriSemaphore* instance) { return count; } + +uint32_t furi_semaphore_get_space(FuriSemaphore* instance) { + furi_assert(instance); + + uint32_t space; + + if(furi_kernel_is_irq_or_masked() != 0U) { + uint32_t isrm = taskENTER_CRITICAL_FROM_ISR(); + + space = instance->container.uxLength - instance->container.uxMessagesWaiting; + + taskEXIT_CRITICAL_FROM_ISR(isrm); + } else { + space = uxQueueSpacesAvailable((QueueHandle_t)instance); + } + + return space; +} + +static FuriEventLoopLink* furi_semaphore_event_loop_get_link(FuriEventLoopObject* object) { + FuriSemaphore* instance = object; + furi_assert(instance); + return &instance->event_loop_link; +} + +static uint32_t + furi_semaphore_event_loop_get_level(FuriEventLoopObject* object, FuriEventLoopEvent event) { + FuriSemaphore* instance = object; + furi_assert(instance); + + if(event == FuriEventLoopEventIn) { + return furi_semaphore_get_count(instance); + } else if(event == FuriEventLoopEventOut) { + return furi_semaphore_get_space(instance); + } else { + furi_crash(); + } +} + +const FuriEventLoopContract furi_semaphore_event_loop_contract = { + .get_link = furi_semaphore_event_loop_get_link, + .get_level = furi_semaphore_event_loop_get_level, +}; diff --git a/furi/core/semaphore.h b/furi/core/semaphore.h index c6b9a1176..47a77ed55 100644 --- a/furi/core/semaphore.h +++ b/furi/core/semaphore.h @@ -53,6 +53,14 @@ FuriStatus furi_semaphore_release(FuriSemaphore* instance); */ uint32_t furi_semaphore_get_count(FuriSemaphore* instance); +/** Get available space + * + * @param instance The pointer to FuriSemaphore instance + * + * @return Semaphore available space + */ +uint32_t furi_semaphore_get_space(FuriSemaphore* instance); + #ifdef __cplusplus } #endif diff --git a/furi/core/stream_buffer.c b/furi/core/stream_buffer.c index ef8869dea..f35abec64 100644 --- a/furi/core/stream_buffer.c +++ b/furi/core/stream_buffer.c @@ -1,13 +1,19 @@ #include "stream_buffer.h" -#include "check.h" -#include "common_defines.h" - #include #include +#include "check.h" +#include "common_defines.h" + +#include "event_loop_link_i.h" + +// Internal FreeRTOS member names +#define xTriggerLevelBytes uxDummy1[3] + struct FuriStreamBuffer { StaticStreamBuffer_t container; + FuriEventLoopLink event_loop_link; uint8_t buffer[]; }; @@ -34,6 +40,10 @@ FuriStreamBuffer* furi_stream_buffer_alloc(size_t size, size_t trigger_level) { void furi_stream_buffer_free(FuriStreamBuffer* stream_buffer) { furi_check(stream_buffer); + // Event Loop must be disconnected + furi_check(!stream_buffer->event_loop_link.item_in); + furi_check(!stream_buffer->event_loop_link.item_out); + vStreamBufferDelete((StreamBufferHandle_t)stream_buffer); free(stream_buffer); } @@ -61,6 +71,16 @@ size_t furi_stream_buffer_send( ret = xStreamBufferSend((StreamBufferHandle_t)stream_buffer, data, length, timeout); } + if(ret > 0) { + const size_t bytes_available = + xStreamBufferBytesAvailable((StreamBufferHandle_t)stream_buffer); + const size_t trigger_level = ((StaticStreamBuffer_t*)stream_buffer)->xTriggerLevelBytes; + + if(bytes_available >= trigger_level) { + furi_event_loop_link_notify(&stream_buffer->event_loop_link, FuriEventLoopEventIn); + } + } + return ret; } @@ -82,6 +102,10 @@ size_t furi_stream_buffer_receive( ret = xStreamBufferReceive((StreamBufferHandle_t)stream_buffer, data, length, timeout); } + if(ret > 0) { + furi_event_loop_link_notify(&stream_buffer->event_loop_link, FuriEventLoopEventOut); + } + return ret; } @@ -112,9 +136,42 @@ bool furi_stream_buffer_is_empty(FuriStreamBuffer* stream_buffer) { FuriStatus furi_stream_buffer_reset(FuriStreamBuffer* stream_buffer) { furi_check(stream_buffer); + FuriStatus status; + if(xStreamBufferReset((StreamBufferHandle_t)stream_buffer) == pdPASS) { - return FuriStatusOk; + status = FuriStatusOk; } else { - return FuriStatusError; + status = FuriStatusError; + } + + if(status == FuriStatusOk) { + furi_event_loop_link_notify(&stream_buffer->event_loop_link, FuriEventLoopEventOut); + } + + return status; +} + +static FuriEventLoopLink* furi_stream_buffer_event_loop_get_link(FuriEventLoopObject* object) { + FuriStreamBuffer* stream_buffer = object; + furi_assert(stream_buffer); + return &stream_buffer->event_loop_link; +} + +static uint32_t + furi_stream_buffer_event_loop_get_level(FuriEventLoopObject* object, FuriEventLoopEvent event) { + FuriStreamBuffer* stream_buffer = object; + furi_assert(stream_buffer); + + if(event == FuriEventLoopEventIn) { + return xStreamBufferBytesAvailable((StreamBufferHandle_t)stream_buffer); + } else if(event == FuriEventLoopEventOut) { + return xStreamBufferSpacesAvailable((StreamBufferHandle_t)stream_buffer); + } else { + furi_crash(); } } + +const FuriEventLoopContract furi_stream_buffer_event_loop_contract = { + .get_link = furi_stream_buffer_event_loop_get_link, + .get_level = furi_stream_buffer_event_loop_get_level, +}; diff --git a/furi/core/string.c b/furi/core/string.c index f3e40fe5e..804445e22 100644 --- a/furi/core/string.c +++ b/furi/core/string.c @@ -17,6 +17,7 @@ struct FuriString { #undef furi_string_replace_all #undef furi_string_start_with #undef furi_string_end_with +#undef furi_string_end_withi #undef furi_string_search_char #undef furi_string_search_rchar #undef furi_string_trim @@ -218,10 +219,28 @@ bool furi_string_end_with(const FuriString* v, const FuriString* v2) { return string_end_with_string_p(v->string, v2->string); } +bool furi_string_end_withi(const FuriString* v, const FuriString* v2) { + return furi_string_end_withi_str(v, string_get_cstr(v2->string)); +} + bool furi_string_end_with_str(const FuriString* v, const char str[]) { return string_end_with_str_p(v->string, str); } +bool furi_string_end_withi_str(const FuriString* v, const char str[]) { + M_STR1NG_CONTRACT(v); + M_ASSERT(str != NULL); + + const size_t str_len = strlen(str); + const size_t v_len = string_size(v->string); + + if(v_len < str_len) { + return false; + } + + return strcasecmp(&string_get_cstr(v->string)[v_len - str_len], str) == 0; +} + size_t furi_string_search_char(const FuriString* v, char c, size_t start) { return string_search_char(v->string, c, start); } diff --git a/furi/core/string.h b/furi/core/string.h index 2bfb60e49..84b8c6a24 100644 --- a/furi/core/string.h +++ b/furi/core/string.h @@ -510,6 +510,15 @@ bool furi_string_start_with_str(const FuriString* string, const char start[]); */ bool furi_string_end_with(const FuriString* string, const FuriString* end); +/** Test if the string ends with the given string (case insensitive according to the current locale). + * + * @param string The FuriString instance + * @param end The end + * + * @return true if string ends with + */ +bool furi_string_end_withi(const FuriString* string, const FuriString* end); + /** Test if the string ends with the given C string. * * @param string The FuriString instance @@ -519,6 +528,15 @@ bool furi_string_end_with(const FuriString* string, const FuriString* end); */ bool furi_string_end_with_str(const FuriString* string, const char end[]); +/** Test if the string ends with the given C string (case insensitive according to the current locale). + * + * @param string The FuriString instance + * @param end The end + * + * @return true if string ends with + */ +bool furi_string_end_withi_str(const FuriString* string, const char end[]); + //--------------------------------------------------------------------------- // Trim //--------------------------------------------------------------------------- @@ -699,6 +717,13 @@ void furi_string_utf8_decode(char c, FuriStringUTF8State* state, FuriStringUnico #define furi_string_end_with(a, b) \ FURI_STRING_SELECT2(furi_string_end_with, furi_string_end_with_str, a, b) +/** Test if the string ends with the given string (or C string) (case insensitive according to the current locale). + * + * (string, [c]string) + */ +#define furi_string_end_withi(a, b) \ + FURI_STRING_SELECT2(furi_string_end_withi, furi_string_end_withi_str, a, b) + /** Append a string (or C string) to the string. * * (string, [c]string) diff --git a/furi/core/thread.c b/furi/core/thread.c index 744d9ad55..becadbc64 100644 --- a/furi/core/thread.c +++ b/furi/core/thread.c @@ -278,6 +278,12 @@ void furi_thread_set_signal_callback( thread->signal_context = context; } +FuriThreadSignalCallback furi_thread_get_signal_callback(const FuriThread* thread) { + furi_check(thread); + + return thread->signal_callback; +} + bool furi_thread_signal(const FuriThread* thread, uint32_t signal, void* arg) { furi_check(thread); diff --git a/furi/core/thread.h b/furi/core/thread.h index be09e040e..e8cdeaeaf 100644 --- a/furi/core/thread.h +++ b/furi/core/thread.h @@ -270,7 +270,7 @@ FuriThreadState furi_thread_get_state(FuriThread* thread); /** * @brief Set a signal handler callback for a FuriThread instance. * - * The thread MUST be stopped when calling this function. + * The thread MUST be stopped when calling this function if calling it from another thread. * * @param[in,out] thread pointer to the FuriThread instance to be modified * @param[in] callback pointer to a user-specified callback function @@ -281,6 +281,14 @@ void furi_thread_set_signal_callback( FuriThreadSignalCallback callback, void* context); +/** + * @brief Get a signal callback for a FuriThread instance. + * + * @param[in] thread pointer to the FuriThread instance to be queried + * @return pointer to the callback function or NULL if none has been set + */ +FuriThreadSignalCallback furi_thread_get_signal_callback(const FuriThread* thread); + /** * @brief Send a signal to a FuriThread instance. * diff --git a/furi/flipper.c b/furi/flipper.c index e5979ffd8..bd138d5f6 100644 --- a/furi/flipper.c +++ b/furi/flipper.c @@ -33,21 +33,24 @@ static void flipper_print_version(const char* target, const Version* version) { } #ifndef FURI_RAM_EXEC -#include -#include -#include +#include #include -#include -#include -#include -#include -#include -#include #include #include #include -#include -#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include void flipper_migrate_files() { Storage* storage = furi_record_open(RECORD_STORAGE); @@ -58,43 +61,53 @@ void flipper_migrate_files() { // Migrate files FURI_LOG_I(TAG, "Migrate: Rename old paths"); + // If multiple have same destination, first match that exists is kept and others deleted const struct { const char* src; const char* dst; - bool delete; } renames[] = { - // Renames on ext - {CFG_PATH("favorites.txt"), ARCHIVE_FAV_PATH, true}, // Adapt to OFW/UL - {CFG_PATH(".desktop.keybinds"), DESKTOP_KEYBINDS_PATH, true}, // Old naming - {CFG_PATH("xtreme_menu.txt"), MAINMENU_APPS_PATH, false}, // Keep both - {CFG_PATH("xtreme_settings.txt"), MOMENTUM_SETTINGS_PATH, false}, // Keep both - // Int -> Ext - {INT_PATH(".bt.settings"), BT_SETTINGS_PATH, true}, - {INT_PATH(".dolphin.state"), DOLPHIN_STATE_PATH, true}, - {INT_PATH(".power.settings"), POWER_SETTINGS_PATH, true}, - {INT_PATH(".bt.keys"), BT_KEYS_STORAGE_PATH, true}, - {INT_PATH(".expansion.settings"), EXPANSION_SETTINGS_PATH, true}, - {INT_PATH(".notification.settings"), NOTIFICATION_SETTINGS_PATH, true}, - {INT_PATH(".infrared.settings"), INFRARED_SETTINGS_PATH, true}, - // Ext -> Int - {CFG_PATH("desktop.settings"), DESKTOP_SETTINGS_PATH, true}, + // Renames on Ext + {EXT_PATH(".config/favorites.txt"), ARCHIVE_FAV_PATH}, // Adapt to OFW/UL + // Ext -> "Int" + {EXT_PATH(".config/bt.keys"), BT_KEYS_STORAGE_PATH}, + {EXT_PATH(".config/bt.settings"), BT_SETTINGS_PATH}, + {EXT_PATH(".config/desktop.keybinds"), DESKTOP_KEYBINDS_PATH_MIGRATE}, + {EXT_PATH(".config/.desktop.keybinds"), DESKTOP_KEYBINDS_PATH_MIGRATE}, // Old naming + {EXT_PATH(".config/desktop.settings"), DESKTOP_SETTINGS_PATH}, + {EXT_PATH(".config/dolphin.state"), DOLPHIN_STATE_PATH}, + {EXT_PATH(".config/expansion.settings"), EXPANSION_SETTINGS_PATH}, + {EXT_PATH(".config/mainmenu_apps.txt"), MAINMENU_APPS_PATH}, + {EXT_PATH(".config/xtreme_menu.txt"), MAINMENU_APPS_PATH}, + {EXT_PATH(".config/momentum_settings.txt"), MOMENTUM_SETTINGS_PATH}, + {EXT_PATH(".config/xtreme_settings.txt"), MOMENTUM_SETTINGS_PATH}, + {EXT_PATH(".config/notification.settings"), NOTIFICATION_SETTINGS_PATH}, + {EXT_PATH(".config/power.settings"), POWER_SETTINGS_PATH}, + {EXT_PATH("dolphin/name.txt"), NAMESPOOF_PATH}, // Adapt to UL + {EXT_PATH("infrared/.infrared.settings"), INFRARED_SETTINGS_PATH}, // Adapt to OFW }; for(size_t i = 0; i < COUNT_OF(renames); ++i) { // Use copy+remove to not overwrite dst but still delete src storage_common_copy(storage, renames[i].src, renames[i].dst); - if(renames[i].delete) { - storage_common_remove(storage, renames[i].src); - } + storage_common_remove(storage, renames[i].src); } - // Special care for U2F + // Int -> Ext for U2F FURI_LOG_I(TAG, "Migrate: U2F"); - FileInfo file_info; - if(storage_common_stat(storage, INT_PATH(".cnt.u2f"), &file_info) == FSE_OK && - file_info.size > 200) { // Is on Int and has content - storage_common_rename(storage, INT_PATH(".cnt.u2f"), U2F_CNT_FILE); // Int -> Ext + if(storage_common_exists(storage, INT_PATH(".cnt.u2f"))) { + const char* cnt_dst = storage_common_exists(storage, U2F_CNT_FILE) ? U2F_CNT_FILE ".old" : + U2F_CNT_FILE; + storage_common_rename(storage, INT_PATH(".cnt.u2f"), cnt_dst); + } + if(storage_common_exists(storage, INT_PATH(".key.u2f"))) { + const char* key_dst = storage_common_exists(storage, U2F_KEY_FILE) ? U2F_KEY_FILE ".old" : + U2F_KEY_FILE; + storage_common_rename(storage, INT_PATH(".key.u2f"), key_dst); + } + + // Remove obsolete .config folder after migration + if(!storage_simply_remove(storage, EXT_PATH(".config"))) { + FURI_LOG_W(TAG, "Can't remove /ext/.config/, probably not empty"); } - storage_common_copy(storage, U2F_DATA_FOLDER "key.u2f", U2F_KEY_FILE); // Ext -> Int // Asset packs migrate, merges together FURI_LOG_I(TAG, "Migrate: Asset Packs"); @@ -102,6 +115,41 @@ void flipper_migrate_files() { furi_record_close(RECORD_STORAGE); } + +// Cannot use pubsub to schedule on SD insert like other services because +// we want migration to happen before others load settings and new pubsub +// subscriptions are put first in callback list so migration would be last +// Also we cannot block the pubsub by loading files as it means storage +// service is deadlocked processing pubsub and cannot process file operations +// So instead storage runs this function in background thread and then +// dispatches the pubsub event to everyone else +bool skip_double_mount = false; +void flipper_mount_callback(const void* message, void* context) { + UNUSED(context); + const StorageEvent* event = message; + + if(event->type == StorageEventTypeCardMount) { + // Workaround to avoid double load on boot but also have animated boot screen + if(skip_double_mount) { + skip_double_mount = false; + return; + } + + // Migrate locations before other services load on SD insert + flipper_migrate_files(); + + // TODO: Need to restart services that already applied previous name + namespoof_init(); + + // TODO: If new SD doesn't contain all current settings IDs, values + // from previous SD are kept for these settings + momentum_settings_load(); + + // TODO: Could lock kernel on free to avoid GUI using assets while being free'd + asset_packs_free(); + asset_packs_init(); + } +} #endif void flipper_start_service(const FlipperInternalApplication* service) { @@ -134,25 +182,32 @@ void flipper_init(void) { #ifndef FURI_RAM_EXEC if(furi_hal_is_normal_boot()) { // Wait for storage record - furi_record_open(RECORD_STORAGE); + Storage* storage = furi_record_open(RECORD_STORAGE); + if(storage_sd_status(storage) != FSE_OK) { + FURI_LOG_D(TAG, "SD Card not ready, skipping early init"); + // Init on SD insert done by storage using flipper_mount_callback() + } else { + // Workaround to avoid double load on boot but also have animated boot screen + skip_double_mount = true; + + canvas_draw_icon(canvas, 39, 43, &I_dir_10px); + canvas_commit(canvas); + flipper_migrate_files(); + + canvas_draw_icon(canvas, 59, 42, &I_Apps_10px); + canvas_commit(canvas); + namespoof_init(); + + canvas_draw_icon(canvas, 79, 44, &I_Rpc_active_7x8); + canvas_commit(canvas); + momentum_settings_load(); + + furi_hal_light_sequence("rgb RB"); + canvas_draw_icon(canvas, 99, 44, &I_Hidden_window_9x8); + canvas_commit(canvas); + asset_packs_init(); + } furi_record_close(RECORD_STORAGE); - - canvas_draw_icon(canvas, 39, 43, &I_dir_10px); - canvas_commit(canvas); - flipper_migrate_files(); - - canvas_draw_icon(canvas, 59, 42, &I_Apps_10px); - canvas_commit(canvas); - namespoof_init(); - - canvas_draw_icon(canvas, 79, 44, &I_Rpc_active_7x8); - canvas_commit(canvas); - momentum_settings_load(); - - furi_hal_light_sequence("rgb RB"); - canvas_draw_icon(canvas, 99, 44, &I_Hidden_window_9x8); - canvas_commit(canvas); - asset_packs_init(); } else { FURI_LOG_I(TAG, "Special boot, skipping optional components"); } diff --git a/furi/flipper.h b/furi/flipper.h index 674cccf88..fe561f5ae 100644 --- a/furi/flipper.h +++ b/furi/flipper.h @@ -1,3 +1,7 @@ #pragma once void flipper_init(void); + +#ifndef FURI_RAM_EXEC +void flipper_mount_callback(const void* message, void* context); +#endif diff --git a/lib/ReadMe.md b/lib/ReadMe.md index 64da39e35..4656f187b 100644 --- a/lib/ReadMe.md +++ b/lib/ReadMe.md @@ -18,7 +18,6 @@ - `infrared` - Infrared library, used by Infrared application - `lfrfid` - LF-RFID library, used by LF RFID application - `libusb_stm32` - LibUSB for STM32 series MCU -- `littlefs` - LittleFS file system driver, used by internal storage - `mbedtls` - MbedTLS cryptography library - `microtar` - MicroTAR library - `mjs` - MJs, javascript engine library diff --git a/lib/SConscript b/lib/SConscript index ccec373b1..27e155523 100644 --- a/lib/SConscript +++ b/lib/SConscript @@ -28,13 +28,11 @@ libs = env.BuildModules( "one_wire", "ibutton", "infrared", - "littlefs", "subghz", "nfc", "digital_signal", "pulse_reader", "signal_reader", - "appframe", "u8g2", "lfrfid", "flipper_application", diff --git a/lib/app-scened-template/generic_scene.hpp b/lib/app-scened-template/generic_scene.hpp deleted file mode 100644 index 580346c8c..000000000 --- a/lib/app-scened-template/generic_scene.hpp +++ /dev/null @@ -1,10 +0,0 @@ -template -class GenericScene { -public: - virtual void on_enter(TApp* app, bool need_restore) = 0; - virtual bool on_event(TApp* app, typename TApp::Event* event) = 0; - virtual void on_exit(TApp* app) = 0; - virtual ~GenericScene() {}; - -private: -}; diff --git a/lib/app-scened-template/record_controller.hpp b/lib/app-scened-template/record_controller.hpp deleted file mode 100644 index 3453c12f3..000000000 --- a/lib/app-scened-template/record_controller.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once -#include - -/** - * @brief Class for opening, casting, holding and closing records - * - * @tparam TRecordClass record class - */ -template -class RecordController { -public: - /** - * @brief Construct a new Record Controller object for record with record name - * - * @param record_name record name - */ - RecordController(const char* record_name) { - name = record_name; - value = static_cast(furi_record_open(name)); - } - - ~RecordController() { - furi_record_close(name); - } - - /** - * @brief Record getter - * - * @return TRecordClass* record value - */ - TRecordClass* get() { - return value; - } - - /** - * @brief Record getter (by cast) - * - * @return TRecordClass* record value - */ - operator TRecordClass*() const { - return value; - } - -private: - const char* name; - TRecordClass* value; -}; diff --git a/lib/app-scened-template/scene_controller.hpp b/lib/app-scened-template/scene_controller.hpp deleted file mode 100644 index eb4310958..000000000 --- a/lib/app-scened-template/scene_controller.hpp +++ /dev/null @@ -1,246 +0,0 @@ -#include -#include -#include - -#define GENERIC_SCENE_ENUM_VALUES Exit, Start -#define GENERIC_EVENT_ENUM_VALUES Tick, Back - -/** - * @brief Controller for scene navigation in application - * - * @tparam TScene generic scene class - * @tparam TApp application class - */ -template -class SceneController { -public: - /** - * @brief Add scene to scene container - * - * @param scene_index scene index - * @param scene_pointer scene object pointer - */ - void add_scene(typename TApp::SceneType scene_index, TScene* scene_pointer) { - furi_check(scenes.count(scene_index) == 0); - scenes[scene_index] = scene_pointer; - } - - /** - * @brief Switch to next scene and store current scene in previous scenes list - * - * @param scene_index next scene index - * @param need_restore true, if we want the scene to restore its parameters - */ - void switch_to_next_scene(typename TApp::SceneType scene_index, bool need_restore = false) { - previous_scenes_list.push_front(current_scene_index); - switch_to_scene(scene_index, need_restore); - } - - /** - * @brief Switch to next scene without ability to return to current scene - * - * @param scene_index next scene index - * @param need_restore true, if we want the scene to restore its parameters - */ - void switch_to_scene(typename TApp::SceneType scene_index, bool need_restore = false) { - if(scene_index != TApp::SceneType::Exit) { - scenes[current_scene_index]->on_exit(app); - current_scene_index = scene_index; - scenes[current_scene_index]->on_enter(app, need_restore); - } - } - - /** - * @brief Search the scene in the list of previous scenes and switch to it - * - * @param scene_index_list list of scene indexes to which you want to switch - */ - bool search_and_switch_to_previous_scene( - const std::initializer_list& scene_index_list) { - auto previous_scene_index = TApp::SceneType::Exit; - bool scene_found = false; - bool result = false; - - while(!scene_found) { - previous_scene_index = get_previous_scene_index(); - for(const auto& element : scene_index_list) { - if(previous_scene_index == element) { - scene_found = true; - result = true; - break; - } - - if(previous_scene_index == TApp::SceneType::Exit) { - scene_found = true; - break; - } - } - } - - if(result) { - switch_to_scene(previous_scene_index, true); - } - - return result; - } - - bool search_and_switch_to_another_scene( - const std::initializer_list& scene_index_list, - typename TApp::SceneType scene_index) { - auto previous_scene_index = TApp::SceneType::Exit; - bool scene_found = false; - bool result = false; - - while(!scene_found) { - previous_scene_index = get_previous_scene_index(); - for(const auto& element : scene_index_list) { - if(previous_scene_index == element) { - scene_found = true; - result = true; - break; - } - - if(previous_scene_index == TApp::SceneType::Exit) { - scene_found = true; - break; - } - } - } - - if(result) { - switch_to_scene(scene_index, true); - } - - return result; - } - - bool has_previous_scene( - const std::initializer_list& scene_index_list) { - bool result = false; - - for(auto const& previous_element : previous_scenes_list) { - for(const auto& element : scene_index_list) { - if(previous_element == element) { - result = true; - break; - } - - if(previous_element == TApp::SceneType::Exit) { - break; - } - } - - if(result) break; - } - - return result; - } - - /** - * @brief Start application main cycle - * - * @param tick_length_ms tick event length in milliseconds - */ - void process( - uint32_t /* tick_length_ms */ = 100, - typename TApp::SceneType start_scene_index = TApp::SceneType::Start) { - typename TApp::Event event; - bool consumed; - bool exit = false; - - current_scene_index = start_scene_index; - scenes[current_scene_index]->on_enter(app, false); - - while(!exit) { - app->view_controller.receive_event(&event); - - consumed = scenes[current_scene_index]->on_event(app, &event); - - if(!consumed) { - if(event.type == TApp::EventType::Back) { - exit = switch_to_previous_scene(); - } - } - }; - - scenes[current_scene_index]->on_exit(app); - } - - /** - * @brief Switch to previous scene - * - * @param count how many steps back - * @return true if app need to exit - */ - bool switch_to_previous_scene(uint8_t count = 1) { - auto previous_scene_index = TApp::SceneType::Start; - - for(uint8_t i = 0; i < count; i++) - previous_scene_index = get_previous_scene_index(); - - if(previous_scene_index == TApp::SceneType::Exit) return true; - - switch_to_scene(previous_scene_index, true); - return false; - } - - /** - * @brief Construct a new Scene Controller object - * - * @param app_pointer pointer to application class - */ - SceneController(TApp* app_pointer) { - app = app_pointer; - current_scene_index = TApp::SceneType::Exit; - } - - /** - * @brief Destroy the Scene Controller object - * - */ - ~SceneController() { - for(auto& it : scenes) - delete it.second; - } - -private: - /** - * @brief Scenes pointers container - * - */ - std::map scenes; - - /** - * @brief List of indexes of previous scenes - * - */ - std::forward_list previous_scenes_list; - - /** - * @brief Current scene index holder - * - */ - typename TApp::SceneType current_scene_index; - - /** - * @brief Application pointer holder - * - */ - TApp* app; - - /** - * @brief Get the previous scene index - * - * @return previous scene index - */ - typename TApp::SceneType get_previous_scene_index() { - auto scene_index = TApp::SceneType::Exit; - - if(!previous_scenes_list.empty()) { - scene_index = previous_scenes_list.front(); - previous_scenes_list.pop_front(); - } - - return scene_index; - } -}; diff --git a/lib/app-scened-template/text_store.cpp b/lib/app-scened-template/text_store.cpp deleted file mode 100644 index c81a2c4e7..000000000 --- a/lib/app-scened-template/text_store.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "text_store.h" -#include - -TextStore::TextStore(uint8_t _text_size) - : text_size(_text_size) { - text = static_cast(malloc(text_size + 1)); -} - -TextStore::~TextStore() { - free(text); -} - -void TextStore::set(const char* _text...) { - va_list args; - va_start(args, _text); - vsnprintf(text, text_size, _text, args); - va_end(args); -} diff --git a/lib/app-scened-template/text_store.h b/lib/app-scened-template/text_store.h deleted file mode 100644 index 3fe58ed1d..000000000 --- a/lib/app-scened-template/text_store.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include - -class TextStore { -public: - TextStore(uint8_t text_size); - ~TextStore(void); - - void set(const char* text...); - const uint8_t text_size; - char* text; -}; diff --git a/lib/app-scened-template/typeindex_no_rtti.hpp b/lib/app-scened-template/typeindex_no_rtti.hpp deleted file mode 100644 index 579a0189d..000000000 --- a/lib/app-scened-template/typeindex_no_rtti.hpp +++ /dev/null @@ -1,129 +0,0 @@ -/* - * type_index without RTTI - * - * Copyright frickiericker 2016. - * Distributed under the Boost Software License, Version 1.0. - * - * Permission is hereby granted, free of charge, to any person or organization - * obtaining a copy of the software and accompanying documentation covered by - * this license (the "Software") to use, reproduce, display, distribute, - * execute, and transmit the Software, and to prepare derivative works of the - * Software, and to permit third-parties to whom the Software is furnished to - * do so, all subject to the following: - * - * The copyright notices in the Software and this entire statement, including - * the above license grant, this restriction and the following disclaimer, - * must be included in all copies of the Software, in whole or in part, and - * all derivative works of the Software, unless such copies or derivative - * works are solely in the form of machine-executable object code generated by - * a source language processor. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT - * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE - * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include - -namespace ext { -/** - * Dummy type for tag-dispatching. - */ -template -struct tag_type {}; - -/** - * A value of tag_type. - */ -template -constexpr tag_type tag{}; - -/** - * A type_index implementation without RTTI. - */ -struct type_index { - /** - * Creates a type_index object for the specified type. - */ - template - type_index(tag_type) noexcept - : hash_code_{index} { - } - - /** - * Returns the hash code. - */ - std::size_t hash_code() const noexcept { - return hash_code_; - } - -private: - /** - * Unique integral index associated to template type argument. - */ - template - static std::size_t const index; - - /** - * Global counter for generating index values. - */ - static std::size_t& counter() noexcept { - static std::size_t counter_; - return counter_; - } - -private: - std::size_t hash_code_; -}; - -template -std::size_t const type_index::index = type_index::counter()++; - -/** - * Creates a type_index object for the specified type. - * - * Equivalent to `ext::type_index{ext::tag}`. - */ -template -type_index make_type_index() noexcept { - return tag; -} - -inline bool operator==(type_index const& a, type_index const& b) noexcept { - return a.hash_code() == b.hash_code(); -} - -inline bool operator!=(type_index const& a, type_index const& b) noexcept { - return !(a == b); -} - -inline bool operator<(type_index const& a, type_index const& b) noexcept { - return a.hash_code() < b.hash_code(); -} - -inline bool operator<=(type_index const& a, type_index const& b) noexcept { - return a.hash_code() <= b.hash_code(); -} - -inline bool operator>(type_index const& a, type_index const& b) noexcept { - return !(a <= b); -} - -inline bool operator>=(type_index const& a, type_index const& b) noexcept { - return !(a < b); -} -} - -template <> -struct std::hash { - using argument_type = ext::type_index; - using result_type = std::size_t; - - result_type operator()(argument_type const& t) const noexcept { - return t.hash_code(); - } -}; diff --git a/lib/app-scened-template/view_controller.hpp b/lib/app-scened-template/view_controller.hpp deleted file mode 100644 index ccd3c0fd3..000000000 --- a/lib/app-scened-template/view_controller.hpp +++ /dev/null @@ -1,170 +0,0 @@ -#pragma once -#include "view_modules/generic_view_module.h" -#include -#include -#include -#include -#include "typeindex_no_rtti.hpp" - -/** - * @brief Controller for switching application views and handling inputs and events - * - * @tparam TApp application class - * @tparam TViewModules variadic list of ViewModules - */ -template -class ViewController { -public: - ViewController() { - event_queue = furi_message_queue_alloc(10, sizeof(typename TApp::Event)); - - view_dispatcher = view_dispatcher_alloc(); - previous_view_callback_pointer = cbc::obtain_connector( - this, &ViewController::previous_view_callback); - - [](...) { - }((this->add_view(ext::make_type_index().hash_code(), new TViewModules()), - 0)...); - - gui = static_cast(furi_record_open("gui")); - } - - ~ViewController() { - for(auto& it : holder) { - view_dispatcher_remove_view(view_dispatcher, static_cast(it.first)); - delete it.second; - } - - view_dispatcher_free(view_dispatcher); - furi_message_queue_free(event_queue); - } - - /** - * @brief Get ViewModule pointer - * - * @tparam T Concrete ViewModule class - * @return T* ViewModule pointer - */ - template - T* get() { - uint32_t view_index = ext::make_type_index().hash_code(); - furi_check(holder.count(view_index) != 0); - return static_cast(holder[view_index]); - } - - /** - * @brief Get ViewModule pointer by cast - * - * @tparam T Concrete ViewModule class - * @return T* ViewModule pointer - */ - template - operator T*() { - uint32_t view_index = ext::make_type_index().hash_code(); - furi_check(holder.count(view_index) != 0); - return static_cast(holder[view_index]); - } - - /** - * @brief Switch view to ViewModule - * - * @tparam T Concrete ViewModule class - * @return T* ViewModule pointer - */ - template - void switch_to() { - uint32_t view_index = ext::make_type_index().hash_code(); - furi_check(holder.count(view_index) != 0); - view_dispatcher_switch_to_view(view_dispatcher, view_index); - } - - /** - * @brief Receive event from app event queue - * - * @param event event pointer - */ - void receive_event(typename TApp::Event* event) { - if(furi_message_queue_get(event_queue, event, 100) != FuriStatusOk) { - event->type = TApp::EventType::Tick; - } - } - - /** - * @brief Send event to app event queue - * - * @param event event pointer - */ - void send_event(typename TApp::Event* event) { - FuriStatus result = furi_message_queue_put(event_queue, event, FuriWaitForever); - furi_check(result == FuriStatusOk); - } - - void attach_to_gui(ViewDispatcherType type) { - view_dispatcher_attach_to_gui(view_dispatcher, gui, type); - } - -private: - /** - * @brief ViewModulesHolder - * - */ - std::map holder; - - /** - * @brief App event queue - * - */ - FuriMessageQueue* event_queue; - - /** - * @brief Main ViewDispatcher pointer - * - */ - ViewDispatcher* view_dispatcher; - - /** - * @brief Gui record pointer - * - */ - Gui* gui; - - /** - * @brief Previous view callback fn pointer - * - */ - ViewNavigationCallback previous_view_callback_pointer; - - /** - * @brief Previous view callback fn - * - * @param context not used - * @return uint32_t VIEW_IGNORE - */ - uint32_t previous_view_callback(void* context) { - (void)context; - - typename TApp::Event event; - event.type = TApp::EventType::Back; - - if(event_queue != NULL) { - send_event(&event); - } - - return VIEW_IGNORE; - } - - /** - * @brief Add ViewModule to holder - * - * @param view_index view index in holder - * @param view_module view module pointer - */ - void add_view(size_t view_index, GenericViewModule* view_module) { - furi_check(holder.count(view_index) == 0); - holder[view_index] = view_module; - - View* view = view_module->get_view(); - view_dispatcher_add_view(view_dispatcher, static_cast(view_index), view); - view_set_previous_callback(view, previous_view_callback_pointer); - } -}; diff --git a/lib/app-scened-template/view_modules/byte_input_vm.cpp b/lib/app-scened-template/view_modules/byte_input_vm.cpp deleted file mode 100644 index 754de9111..000000000 --- a/lib/app-scened-template/view_modules/byte_input_vm.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "byte_input_vm.h" - -ByteInputVM::ByteInputVM() { - byte_input = byte_input_alloc(); -} - -ByteInputVM::~ByteInputVM() { - byte_input_free(byte_input); -} - -View* ByteInputVM::get_view() { - return byte_input_get_view(byte_input); -} - -void ByteInputVM::clean() { - byte_input_set_header_text(byte_input, ""); - byte_input_set_result_callback(byte_input, NULL, NULL, NULL, NULL, 0); -} - -void ByteInputVM::set_result_callback( - ByteInputCallback input_callback, - ByteChangedCallback changed_callback, - void* callback_context, - uint8_t* bytes, - uint8_t bytes_count) { - byte_input_set_result_callback( - byte_input, input_callback, changed_callback, callback_context, bytes, bytes_count); -} - -void ByteInputVM::set_header_text(const char* text) { - byte_input_set_header_text(byte_input, text); -} diff --git a/lib/app-scened-template/view_modules/byte_input_vm.h b/lib/app-scened-template/view_modules/byte_input_vm.h deleted file mode 100644 index 69031fbee..000000000 --- a/lib/app-scened-template/view_modules/byte_input_vm.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once -#include "generic_view_module.h" -#include - -class ByteInputVM : public GenericViewModule { -public: - ByteInputVM(void); - ~ByteInputVM() final; - View* get_view() final; - void clean() final; - - /** - * @brief Set byte input result callback - * - * @param input_callback input callback fn - * @param changed_callback changed callback fn - * @param callback_context callback context - * @param bytes buffer to use - * @param bytes_count buffer length - */ - void set_result_callback( - ByteInputCallback input_callback, - ByteChangedCallback changed_callback, - void* callback_context, - uint8_t* bytes, - uint8_t bytes_count); - - /** - * @brief Set byte input header text - * - * @param text text to be shown - */ - void set_header_text(const char* text); - -private: - ByteInput* byte_input; -}; diff --git a/lib/app-scened-template/view_modules/dialog_ex_vm.cpp b/lib/app-scened-template/view_modules/dialog_ex_vm.cpp deleted file mode 100644 index 34f4d0336..000000000 --- a/lib/app-scened-template/view_modules/dialog_ex_vm.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "dialog_ex_vm.h" - -DialogExVM::DialogExVM() { - dialog_ex = dialog_ex_alloc(); -} - -DialogExVM::~DialogExVM() { - dialog_ex_free(dialog_ex); -} - -View* DialogExVM::get_view() { - return dialog_ex_get_view(dialog_ex); -} - -void DialogExVM::clean() { - set_result_callback(NULL); - set_context(NULL); - set_header(NULL, 0, 0, AlignLeft, AlignBottom); - set_text(NULL, 0, 0, AlignLeft, AlignBottom); - set_icon(0, 0, NULL); - set_left_button_text(NULL); - set_center_button_text(NULL); - set_right_button_text(NULL); -} - -void DialogExVM::set_result_callback(DialogExResultCallback callback) { - dialog_ex_set_result_callback(dialog_ex, callback); -} - -void DialogExVM::set_context(void* context) { - dialog_ex_set_context(dialog_ex, context); -} - -void DialogExVM::set_header( - const char* text, - uint8_t x, - uint8_t y, - Align horizontal, - Align vertical) { - dialog_ex_set_header(dialog_ex, text, x, y, horizontal, vertical); -} - -void DialogExVM::set_text(const char* text, uint8_t x, uint8_t y, Align horizontal, Align vertical) { - dialog_ex_set_text(dialog_ex, text, x, y, horizontal, vertical); -} - -void DialogExVM::set_icon(uint8_t x, uint8_t y, const Icon* icon) { - dialog_ex_set_icon(dialog_ex, x, y, icon); -} - -void DialogExVM::set_left_button_text(const char* text) { - dialog_ex_set_left_button_text(dialog_ex, text); -} - -void DialogExVM::set_center_button_text(const char* text) { - dialog_ex_set_center_button_text(dialog_ex, text); -} - -void DialogExVM::set_right_button_text(const char* text) { - dialog_ex_set_right_button_text(dialog_ex, text); -} diff --git a/lib/app-scened-template/view_modules/dialog_ex_vm.h b/lib/app-scened-template/view_modules/dialog_ex_vm.h deleted file mode 100644 index cb63ccdbc..000000000 --- a/lib/app-scened-template/view_modules/dialog_ex_vm.h +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once -#include "generic_view_module.h" -#include - -class DialogExVM : public GenericViewModule { -public: - DialogExVM(void); - ~DialogExVM() final; - View* get_view() final; - void clean() final; - - /** - * Set dialog result callback - * @param callback - result callback function - */ - void set_result_callback(DialogExResultCallback callback); - - /** - * Set dialog context - * @param context - context pointer, will be passed to result callback - */ - void set_context(void* context); - - /** - * Set dialog header text - * If text is null, dialog header will not be rendered - * @param text - text to be shown, can be multiline - * @param x, y - text position - * @param horizontal, vertical - text aligment - */ - void set_header(const char* text, uint8_t x, uint8_t y, Align horizontal, Align vertical); - - /** - * Set dialog text - * If text is null, dialog text will not be rendered - * @param text - text to be shown, can be multiline - * @param x, y - text position - * @param horizontal, vertical - text aligment - */ - void set_text(const char* text, uint8_t x, uint8_t y, Align horizontal, Align vertical); - - /** - * Set dialog icon - * If x or y is negative, dialog icon will not be rendered - * @param x, y - icon position - * @param name - icon to be shown - */ - void set_icon(uint8_t x, uint8_t y, const Icon* icon); - - /** - * Set left button text - * If text is null, left button will not be rendered and processed - * @param text - text to be shown - */ - void set_left_button_text(const char* text); - - /** - * Set center button text - * If text is null, center button will not be rendered and processed - * @param text - text to be shown - */ - void set_center_button_text(const char* text); - - /** - * Set right button text - * If text is null, right button will not be rendered and processed - * @param text - text to be shown - */ - void set_right_button_text(const char* text); - -private: - DialogEx* dialog_ex; -}; diff --git a/lib/app-scened-template/view_modules/generic_view_module.h b/lib/app-scened-template/view_modules/generic_view_module.h deleted file mode 100644 index f6c56a911..000000000 --- a/lib/app-scened-template/view_modules/generic_view_module.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once -#include - -class GenericViewModule { -public: - GenericViewModule() {}; - virtual ~GenericViewModule() {}; - virtual View* get_view() = 0; - virtual void clean() = 0; -}; diff --git a/lib/app-scened-template/view_modules/popup_vm.cpp b/lib/app-scened-template/view_modules/popup_vm.cpp deleted file mode 100644 index 330aa44ca..000000000 --- a/lib/app-scened-template/view_modules/popup_vm.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "popup_vm.h" -#include - -PopupVM::PopupVM() { - popup = popup_alloc(); -} - -PopupVM::~PopupVM() { - popup_free(popup); -} - -View* PopupVM::get_view() { - return popup_get_view(popup); -} - -void PopupVM::clean() { - set_callback(NULL); - set_context(NULL); - set_header(NULL, 0, 0, AlignLeft, AlignBottom); - set_text(NULL, 0, 0, AlignLeft, AlignBottom); - set_icon(0, 0, NULL); - disable_timeout(); - set_timeout(1000); -} - -void PopupVM::set_callback(PopupCallback callback) { - popup_set_callback(popup, callback); -} - -void PopupVM::set_context(void* context) { - popup_set_context(popup, context); -} - -void PopupVM::set_header(const char* text, uint8_t x, uint8_t y, Align horizontal, Align vertical) { - popup_set_header(popup, text, x, y, horizontal, vertical); -} - -void PopupVM::set_text(const char* text, uint8_t x, uint8_t y, Align horizontal, Align vertical) { - popup_set_text(popup, text, x, y, horizontal, vertical); -} - -void PopupVM::set_icon(int8_t x, int8_t y, const Icon* icon) { - popup_set_icon(popup, x, y, icon); -} - -void PopupVM::set_timeout(uint32_t timeout_in_ms) { - popup_set_timeout(popup, timeout_in_ms); -} - -void PopupVM::enable_timeout() { - popup_enable_timeout(popup); -} - -void PopupVM::disable_timeout() { - popup_disable_timeout(popup); -} diff --git a/lib/app-scened-template/view_modules/popup_vm.h b/lib/app-scened-template/view_modules/popup_vm.h deleted file mode 100644 index 234f33774..000000000 --- a/lib/app-scened-template/view_modules/popup_vm.h +++ /dev/null @@ -1,68 +0,0 @@ -#pragma once -#include "generic_view_module.h" -#include - -class PopupVM : public GenericViewModule { -public: - PopupVM(void); - ~PopupVM() final; - View* get_view() final; - void clean() final; - - /** - * Set popup header text - * @param text - text to be shown - */ - void set_callback(PopupCallback callback); - - /** - * Set popup context - * @param context - context pointer, will be passed to result callback - */ - void set_context(void* context); - - /** - * Set popup header text - * If text is null, popup header will not be rendered - * @param text - text to be shown, can be multiline - * @param x, y - text position - * @param horizontal, vertical - text aligment - */ - void set_header(const char* text, uint8_t x, uint8_t y, Align horizontal, Align vertical); - - /** - * Set popup text - * If text is null, popup text will not be rendered - * @param text - text to be shown, can be multiline - * @param x, y - text position - * @param horizontal, vertical - text aligment - */ - void set_text(const char* text, uint8_t x, uint8_t y, Align horizontal, Align vertical); - - /** - * Set popup icon - * If icon position is negative, popup icon will not be rendered - * @param x, y - icon position - * @param name - icon to be shown - */ - void set_icon(int8_t x, int8_t y, const Icon* icon); - - /** - * Set popup timeout - * @param timeout_in_ms - popup timeout value in milliseconds - */ - void set_timeout(uint32_t timeout_in_ms); - - /** - * Enable popup timeout - */ - void enable_timeout(void); - - /** - * Disable popup timeout - */ - void disable_timeout(void); - -private: - Popup* popup; -}; diff --git a/lib/app-scened-template/view_modules/submenu_vm.cpp b/lib/app-scened-template/view_modules/submenu_vm.cpp deleted file mode 100644 index 939bb6b1c..000000000 --- a/lib/app-scened-template/view_modules/submenu_vm.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "submenu_vm.h" - -SubmenuVM::SubmenuVM() { - submenu = submenu_alloc(); -} - -SubmenuVM::~SubmenuVM() { - submenu_free(submenu); -} - -View* SubmenuVM::get_view() { - return submenu_get_view(submenu); -} - -void SubmenuVM::clean() { - submenu_reset(submenu); -} - -void SubmenuVM::add_item( - const char* label, - uint32_t index, - SubmenuItemCallback callback, - void* callback_context) { - submenu_add_item(submenu, label, index, callback, callback_context); -} - -void SubmenuVM::set_selected_item(uint32_t index) { - submenu_set_selected_item(submenu, index); -} - -void SubmenuVM::set_header(const char* header) { - submenu_set_header(submenu, header); -} diff --git a/lib/app-scened-template/view_modules/submenu_vm.h b/lib/app-scened-template/view_modules/submenu_vm.h deleted file mode 100644 index 223fbd531..000000000 --- a/lib/app-scened-template/view_modules/submenu_vm.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once -#include "generic_view_module.h" -#include - -class SubmenuVM : public GenericViewModule { -public: - SubmenuVM(void); - ~SubmenuVM() final; - View* get_view() final; - void clean() final; - - /** - * @brief Add item to submenu - * - * @param label - menu item label - * @param index - menu item index, used for callback, may be the same with other items - * @param callback - menu item callback - * @param callback_context - menu item callback context - */ - void add_item( - const char* label, - uint32_t index, - SubmenuItemCallback callback, - void* callback_context); - - /** - * @brief Set submenu item selector - * - * @param index index of the item to be selected - */ - void set_selected_item(uint32_t index); - - /** - * @brief Set optional header for submenu - * - * @param header header to set - */ - void set_header(const char* header); - -private: - Submenu* submenu; -}; diff --git a/lib/app-scened-template/view_modules/text_input_vm.cpp b/lib/app-scened-template/view_modules/text_input_vm.cpp deleted file mode 100644 index 05e5ed1d6..000000000 --- a/lib/app-scened-template/view_modules/text_input_vm.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "text_input_vm.h" - -TextInputVM::TextInputVM() { - text_input = text_input_alloc(); -} - -TextInputVM::~TextInputVM() { - text_input_free(text_input); -} - -View* TextInputVM::get_view() { - return text_input_get_view(text_input); -} - -void TextInputVM::clean() { - text_input_reset(text_input); -} - -void TextInputVM::set_result_callback( - TextInputCallback callback, - void* callback_context, - char* text, - uint8_t max_text_length, - bool clear_default_text) { - text_input_set_result_callback( - text_input, callback, callback_context, text, max_text_length, clear_default_text); -} - -void TextInputVM::set_header_text(const char* text) { - text_input_set_header_text(text_input, text); -} - -void TextInputVM::set_validator(TextInputValidatorCallback callback, void* callback_context) { - text_input_set_validator(text_input, callback, callback_context); -} - -void* TextInputVM::get_validator_callback_context() { - return text_input_get_validator_callback_context(text_input); -} diff --git a/lib/app-scened-template/view_modules/text_input_vm.h b/lib/app-scened-template/view_modules/text_input_vm.h deleted file mode 100644 index 5c71c4318..000000000 --- a/lib/app-scened-template/view_modules/text_input_vm.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once -#include "generic_view_module.h" -#include - -class TextInputVM : public GenericViewModule { -public: - TextInputVM(void); - ~TextInputVM() final; - View* get_view() final; - void clean() final; - - /** - * @brief Set text input result callback - * - * @param callback - callback fn - * @param callback_context - callback context - * @param text - text buffer to use - * @param max_text_length - text buffer length - * @param clear_default_text - clears given buffer on OK event - */ - void set_result_callback( - TextInputCallback callback, - void* callback_context, - char* text, - uint8_t max_text_length, - bool clear_default_text); - - /** - * @brief Set text input header text - * - * @param text - text to be shown - */ - void set_header_text(const char* text); - - void set_validator(TextInputValidatorCallback callback, void* callback_context); - - void* get_validator_callback_context(void); - -private: - TextInput* text_input; -}; diff --git a/lib/appframe.scons b/lib/appframe.scons deleted file mode 100644 index fb268579d..000000000 --- a/lib/appframe.scons +++ /dev/null @@ -1,29 +0,0 @@ -Import("env") - -env.Append( - CPPPATH=[ - "#/lib/app-scened-template", - "#/lib/callback-connector", - ], - LINT_SOURCES=[ - Dir("app-scened-template"), - ], -) - - -libenv = env.Clone(FW_LIB_NAME="appframe") -libenv.ApplyLibFlags() - -sources = [] - -recurse_dirs = [ - "app-scened-template", - "callback-connector", -] - -for recurse_dir in recurse_dirs: - sources += libenv.GlobRecursive("*.c*", recurse_dir) - -lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources) -libenv.Install("${LIB_DIST_DIR}", lib) -Return("lib") diff --git a/lib/ble_profile/extra_profiles/hid_profile.c b/lib/ble_profile/extra_profiles/hid_profile.c index 91a1e8286..19e057fab 100644 --- a/lib/ble_profile/extra_profiles/hid_profile.c +++ b/lib/ble_profile/extra_profiles/hid_profile.c @@ -373,6 +373,12 @@ bool ble_profile_hid_mouse_scroll(FuriHalBleProfileBase* profile, int8_t delta) return state; } +// AN5289: 4.7, in order to use flash controller interval must be at least 25ms + advertisement, which is 30 ms +// Since we don't use flash controller anymore interval can be lowered to 7.5ms +#define CONNECTION_INTERVAL_MIN (0x0006) +// Up to 45 ms +#define CONNECTION_INTERVAL_MAX (0x24) + static GapConfig template_config = { .adv_service_uuid = HUMAN_INTERFACE_DEVICE_SERVICE_UUID, .appearance_char = GAP_APPEARANCE_KEYBOARD, @@ -380,8 +386,8 @@ static GapConfig template_config = { .pairing_method = GapPairingPinCodeVerifyYesNo, .conn_param = { - .conn_int_min = 0x18, // AN5289: 4.7, we need at least 25ms + advertisement, which is 30 ms - .conn_int_max = 0x24, // 45 ms + .conn_int_min = CONNECTION_INTERVAL_MIN, + .conn_int_max = CONNECTION_INTERVAL_MAX, .slave_latency = 0, .supervisor_timeout = 0, }, diff --git a/lib/drivers/rgb_backlight.c b/lib/drivers/rgb_backlight.c index 1995c0d17..0c4433509 100644 --- a/lib/drivers/rgb_backlight.c +++ b/lib/drivers/rgb_backlight.c @@ -24,7 +24,7 @@ #define RGB_BACKLIGHT_SETTINGS_MAGIC 0x15 #define RGB_BACKLIGHT_SETTINGS_VERSION 6 -#define RGB_BACKLIGHT_SETTINGS_PATH CFG_PATH("rgb_backlight.settings") +#define RGB_BACKLIGHT_SETTINGS_PATH INT_PATH(".rgb_backlight.settings") static struct { RgbColor colors[SK6805_LED_COUNT]; @@ -62,11 +62,16 @@ static struct { }; void rgb_backlight_load_settings(bool enabled) { - if(rgb_state.settings_loaded) return; - rgb_state.enabled = enabled; - rgb_state.mutex = furi_mutex_alloc(FuriMutexTypeRecursive); + // This function is called from momentum_settings_load() + // No need to setup storage pubsub, just expect multiple calls - // Do not load data from internal memory when booting in DFU mode + rgb_state.settings_loaded = false; + rgb_state.enabled = enabled; + if(!rgb_state.mutex) { + rgb_state.mutex = furi_mutex_alloc(FuriMutexTypeRecursive); + } + + // Do not load and apply settings when booting in update/RAM mode if(!furi_hal_is_normal_boot()) { rgb_state.settings_loaded = true; return; diff --git a/lib/drivers/st25r3916.c b/lib/drivers/st25r3916.c index 477261213..f8dc9a5eb 100644 --- a/lib/drivers/st25r3916.c +++ b/lib/drivers/st25r3916.c @@ -57,9 +57,12 @@ bool st25r3916_read_fifo( do { uint8_t fifo_status[2] = {}; st25r3916_read_burst_regs(handle, ST25R3916_REG_FIFO_STATUS1, fifo_status, 2); - size_t bytes = ((fifo_status[1] & ST25R3916_REG_FIFO_STATUS2_fifo_b_mask) >> - ST25R3916_REG_FIFO_STATUS2_fifo_b_shift) | - fifo_status[0]; + + uint16_t fifo_status_b9_b8 = + ((fifo_status[1] & ST25R3916_REG_FIFO_STATUS2_fifo_b_mask) >> + ST25R3916_REG_FIFO_STATUS2_fifo_b_shift); + size_t bytes = (fifo_status_b9_b8 << 8) | fifo_status[0]; + uint8_t bits = ((fifo_status[1] & ST25R3916_REG_FIFO_STATUS2_fifo_lb_mask) >> ST25R3916_REG_FIFO_STATUS2_fifo_lb_shift); diff --git a/lib/lfs_config.h b/lib/lfs_config.h deleted file mode 100644 index ff8bc4b23..000000000 --- a/lib/lfs_config.h +++ /dev/null @@ -1,204 +0,0 @@ -#pragma once - -#include - -#ifdef FURI_NDEBUG -#define LFS_NO_ASSERT -#define LFS_ASSERT(x) -#else -#define LFS_ASSERT furi_assert -#endif - -#define LFS_TAG "Lfs" - -#ifdef FURI_LFS_DEBUG -#define LFS_TRACE(...) FURI_LOG_T(LFS_TAG, __VA_ARGS__); - -#define LFS_DEBUG(...) FURI_LOG_D(LFS_TAG, __VA_ARGS__); -#else -#define LFS_TRACE(...) - -#define LFS_DEBUG(...) -#endif // FURI_LFS_DEBUG - -#define LFS_WARN(...) FURI_LOG_W(LFS_TAG, __VA_ARGS__); - -#define LFS_ERROR(...) FURI_LOG_E(LFS_TAG, __VA_ARGS__); - -// Because crc -#undef LFS_CONFIG - -// System includes -#include -#include -#include -#include - -#ifndef LFS_NO_MALLOC -#include -#endif -#ifndef LFS_NO_ASSERT -#include -#endif -#if !defined(LFS_NO_DEBUG) || !defined(LFS_NO_WARN) || !defined(LFS_NO_ERROR) || \ - defined(LFS_YES_TRACE) -#include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -// Builtin functions, these may be replaced by more efficient -// toolchain-specific implementations. LFS_NO_INTRINSICS falls back to a more -// expensive basic C implementation for debugging purposes - -// Min/max functions for unsigned 32-bit numbers -static inline uint32_t lfs_max(uint32_t a, uint32_t b) { - return (a > b) ? a : b; -} - -static inline uint32_t lfs_min(uint32_t a, uint32_t b) { - return (a < b) ? a : b; -} - -// Align to nearest multiple of a size -static inline uint32_t lfs_aligndown(uint32_t a, uint32_t alignment) { - return a - (a % alignment); -} - -static inline uint32_t lfs_alignup(uint32_t a, uint32_t alignment) { - return lfs_aligndown(a + alignment - 1, alignment); -} - -// Find the smallest power of 2 greater than or equal to a -static inline uint32_t lfs_npw2(uint32_t a) { -#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM)) - return 32 - __builtin_clz(a - 1); -#else - uint32_t r = 0; - uint32_t s; - a -= 1; - s = (a > 0xffff) << 4; - a >>= s; - r |= s; - s = (a > 0xff) << 3; - a >>= s; - r |= s; - s = (a > 0xf) << 2; - a >>= s; - r |= s; - s = (a > 0x3) << 1; - a >>= s; - r |= s; - return (r | (a >> 1)) + 1; -#endif -} - -// Count the number of trailing binary zeros in a -// lfs_ctz(0) may be undefined -static inline uint32_t lfs_ctz(uint32_t a) { -#if !defined(LFS_NO_INTRINSICS) && defined(__GNUC__) - return __builtin_ctz(a); -#else - return lfs_npw2((a & -a) + 1) - 1; -#endif -} - -// Count the number of binary ones in a -static inline uint32_t lfs_popc(uint32_t a) { -#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM)) - return __builtin_popcount(a); -#else - a = a - ((a >> 1) & 0x55555555); - a = (a & 0x33333333) + ((a >> 2) & 0x33333333); - return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24; -#endif -} - -// Find the sequence comparison of a and b, this is the distance -// between a and b ignoring overflow -static inline int lfs_scmp(uint32_t a, uint32_t b) { - return (int)(unsigned)(a - b); -} - -// Convert between 32-bit little-endian and native order -static inline uint32_t lfs_fromle32(uint32_t a) { -#if !defined(LFS_NO_INTRINSICS) && \ - ((defined(BYTE_ORDER) && defined(ORDER_LITTLE_ENDIAN) && \ - BYTE_ORDER == ORDER_LITTLE_ENDIAN) || \ - (defined(__BYTE_ORDER) && defined(__ORDER_LITTLE_ENDIAN) && \ - __BYTE_ORDER == __ORDER_LITTLE_ENDIAN) || \ - (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \ - __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) - return a; -#elif !defined(LFS_NO_INTRINSICS) && \ - ((defined(BYTE_ORDER) && defined(ORDER_BIG_ENDIAN) && BYTE_ORDER == ORDER_BIG_ENDIAN) || \ - (defined(__BYTE_ORDER) && defined(__ORDER_BIG_ENDIAN) && \ - __BYTE_ORDER == __ORDER_BIG_ENDIAN) || \ - (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \ - __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) - return __builtin_bswap32(a); -#else - return (((uint8_t*)&a)[0] << 0) | (((uint8_t*)&a)[1] << 8) | (((uint8_t*)&a)[2] << 16) | - (((uint8_t*)&a)[3] << 24); -#endif -} - -static inline uint32_t lfs_tole32(uint32_t a) { - return lfs_fromle32(a); -} - -// Convert between 32-bit big-endian and native order -static inline uint32_t lfs_frombe32(uint32_t a) { -#if !defined(LFS_NO_INTRINSICS) && \ - ((defined(BYTE_ORDER) && defined(ORDER_LITTLE_ENDIAN) && \ - BYTE_ORDER == ORDER_LITTLE_ENDIAN) || \ - (defined(__BYTE_ORDER) && defined(__ORDER_LITTLE_ENDIAN) && \ - __BYTE_ORDER == __ORDER_LITTLE_ENDIAN) || \ - (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \ - __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) - return __builtin_bswap32(a); -#elif !defined(LFS_NO_INTRINSICS) && \ - ((defined(BYTE_ORDER) && defined(ORDER_BIG_ENDIAN) && BYTE_ORDER == ORDER_BIG_ENDIAN) || \ - (defined(__BYTE_ORDER) && defined(__ORDER_BIG_ENDIAN) && \ - __BYTE_ORDER == __ORDER_BIG_ENDIAN) || \ - (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \ - __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) - return a; -#else - return (((uint8_t*)&a)[0] << 24) | (((uint8_t*)&a)[1] << 16) | (((uint8_t*)&a)[2] << 8) | - (((uint8_t*)&a)[3] << 0); -#endif -} - -static inline uint32_t lfs_tobe32(uint32_t a) { - return lfs_frombe32(a); -} - -// Calculate CRC-32 with polynomial = 0x04c11db7 -uint32_t lfs_crc(uint32_t crc, const void* buffer, size_t size); - -// Allocate memory, only used if buffers are not provided to littlefs -// Note, memory must be 64-bit aligned -static inline void* lfs_malloc(size_t size) { -#ifndef LFS_NO_MALLOC - return malloc(size); -#else - (void)size; - return NULL; -#endif -} - -// Deallocate memory, only used if buffers are not provided to littlefs -static inline void lfs_free(void* p) { -#ifndef LFS_NO_MALLOC - free(p); -#else - (void)p; -#endif -} - -#ifdef __cplusplus -} /* extern "C" */ -#endif diff --git a/lib/littlefs b/lib/littlefs deleted file mode 160000 index 611c9b20d..000000000 --- a/lib/littlefs +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 611c9b20db2b99faee261daa7cc9bbe175d3eaca diff --git a/lib/littlefs.scons b/lib/littlefs.scons deleted file mode 100644 index 3d68e07ba..000000000 --- a/lib/littlefs.scons +++ /dev/null @@ -1,22 +0,0 @@ -Import("env") - -env.Append( - CPPPATH=[ - "#/lib/littlefs", - ], -) - - -libenv = env.Clone(FW_LIB_NAME="littlefs") -libenv.ApplyLibFlags() -libenv.Append( - CPPDEFINES=[ - ("LFS_CONFIG", "lfs_config.h"), - ], -) - -sources = Glob("littlefs/*.c", source=True) - -lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources) -libenv.Install("${LIB_DIST_DIR}", lib) -Return("lib") diff --git a/lib/momentum/namespoof.c b/lib/momentum/namespoof.c index 74e87c7bb..b2aa61399 100644 --- a/lib/momentum/namespoof.c +++ b/lib/momentum/namespoof.c @@ -10,6 +10,9 @@ void namespoof_init(void) { Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* file = flipper_format_file_alloc(storage); + const char* prev_custom_name = version_get_custom_name(NULL); + bool applied_new_name = false; + do { uint32_t version; if(!flipper_format_file_open_existing(file, NAMESPOOF_PATH)) break; @@ -20,8 +23,17 @@ void namespoof_init(void) { if(!flipper_format_read_string(file, "Name", str)) break; version_set_custom_name(NULL, strdup(furi_string_get_cstr(str))); furi_hal_version_set_name(NULL); + applied_new_name = true; } while(false); + if(prev_custom_name) { + if(!applied_new_name) { + version_set_custom_name(NULL, NULL); + furi_hal_version_init(); + } + free((void*)prev_custom_name); + } + flipper_format_free(file); furi_record_close(RECORD_STORAGE); furi_string_free(str); diff --git a/lib/momentum/namespoof.h b/lib/momentum/namespoof.h index 49bb51a6a..31bec942d 100644 --- a/lib/momentum/namespoof.h +++ b/lib/momentum/namespoof.h @@ -2,6 +2,6 @@ #define NAMESPOOF_HEADER "Flipper Name File" #define NAMESPOOF_VERSION 1 -#define NAMESPOOF_PATH EXT_PATH("dolphin/name.txt") +#define NAMESPOOF_PATH EXT_PATH("dolphin/name.settings") void namespoof_init(void); diff --git a/lib/momentum/settings.c b/lib/momentum/settings.c index 413c38d0e..315124c7c 100644 --- a/lib/momentum/settings.c +++ b/lib/momentum/settings.c @@ -23,7 +23,6 @@ MomentumSettings momentum_settings = { .lockscreen_prompt = true, // ON .lockscreen_transparent = false, // OFF .battery_icon = BatteryIconBarPercent, // Bar % - .statusbar_clock = false, // OFF .status_icons = true, // ON .bar_borders = true, // ON .bar_background = false, // OFF @@ -93,7 +92,6 @@ static const struct { {setting_bool(lockscreen_prompt)}, {setting_bool(lockscreen_transparent)}, {setting_enum(battery_icon, BatteryIconCount)}, - {setting_bool(statusbar_clock)}, {setting_bool(status_icons)}, {setting_bool(bar_borders)}, {setting_bool(bar_background)}, diff --git a/lib/momentum/settings.h b/lib/momentum/settings.h index 4d46700c1..ee1341131 100644 --- a/lib/momentum/settings.h +++ b/lib/momentum/settings.h @@ -5,7 +5,7 @@ #include #include -#define MOMENTUM_SETTINGS_PATH CFG_PATH("momentum_settings.txt") +#define MOMENTUM_SETTINGS_PATH INT_PATH(".momentum_settings.txt") #define ASSET_PACKS_NAME_LEN 32 @@ -71,7 +71,6 @@ typedef struct { bool lockscreen_prompt; bool lockscreen_transparent; BatteryIcon battery_icon; - bool statusbar_clock; bool status_icons; bool bar_borders; bool bar_background; diff --git a/lib/subghz/devices/registry.c b/lib/subghz/devices/registry.c index cf044c98a..9722c1501 100644 --- a/lib/subghz/devices/registry.c +++ b/lib/subghz/devices/registry.c @@ -23,8 +23,8 @@ void subghz_device_registry_init(void) { firmware_api_interface); //TODO FL-3556: fix path to plugins - //if(plugin_manager_load_all(subghz_device->manager, APP_DATA_PATH("plugins")) != - if(plugin_manager_load_all(subghz_device->manager, "/ext/apps_data/subghz/plugins") != + if(plugin_manager_load_all(subghz_device->manager, EXT_PATH("apps_data/subghz/plugins")) != + //if(plugin_manager_load_all(subghz_device->manager, APP_DATA_PATH("plugins")) != PluginManagerErrorNone) { FURI_LOG_E(TAG, "Failed to load all libs"); } diff --git a/lib/subghz/protocols/dickert_mahs.c b/lib/subghz/protocols/dickert_mahs.c new file mode 100644 index 000000000..d3c5146f0 --- /dev/null +++ b/lib/subghz/protocols/dickert_mahs.c @@ -0,0 +1,387 @@ +#include "dickert_mahs.h" + +#include "../blocks/const.h" +#include "../blocks/decoder.h" +#include "../blocks/encoder.h" +#include "../blocks/generic.h" +#include "../blocks/math.h" + +#include +#include +#include + +#define TAG "SubGhzProtocolDicketMAHS" + +static const SubGhzBlockConst subghz_protocol_dickert_mahs_const = { + .te_short = 400, + .te_long = 800, + .te_delta = 100, + .min_count_bit_for_found = 36, +}; + +struct SubGhzProtocolDecoderDickertMAHS { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + SubGhzBlockGeneric generic; + + uint32_t tmp[2]; + uint8_t tmp_cnt; +}; + +struct SubGhzProtocolEncoderDickertMAHS { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + SubGhzBlockGeneric generic; +}; + +typedef enum { + DickertMAHSDecoderStepReset = 0, + DickertMAHSDecoderStepInitial, + DickertMAHSDecoderStepRecording, +} DickertMAHSDecoderStep; + +const SubGhzProtocolDecoder subghz_protocol_dickert_mahs_decoder = { + .alloc = subghz_protocol_decoder_dickert_mahs_alloc, + .free = subghz_protocol_decoder_dickert_mahs_free, + + .feed = subghz_protocol_decoder_dickert_mahs_feed, + .reset = subghz_protocol_decoder_dickert_mahs_reset, + + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_dickert_mahs_get_hash_data, + .serialize = subghz_protocol_decoder_dickert_mahs_serialize, + .deserialize = subghz_protocol_decoder_dickert_mahs_deserialize, + .get_string = subghz_protocol_decoder_dickert_mahs_get_string, + .get_string_brief = NULL, +}; + +const SubGhzProtocolEncoder subghz_protocol_dickert_mahs_encoder = { + .alloc = subghz_protocol_encoder_dickert_mahs_alloc, + .free = subghz_protocol_encoder_dickert_mahs_free, + + .deserialize = subghz_protocol_encoder_dickert_mahs_deserialize, + .stop = subghz_protocol_encoder_dickert_mahs_stop, + .yield = subghz_protocol_encoder_dickert_mahs_yield, +}; + +const SubGhzProtocol subghz_protocol_dickert_mahs = { + .name = SUBGHZ_PROTOCOL_DICKERT_MAHS_NAME, + .type = SubGhzProtocolTypeStatic, + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send, + + .decoder = &subghz_protocol_dickert_mahs_decoder, + .encoder = &subghz_protocol_dickert_mahs_encoder, +}; + +static void subghz_protocol_encoder_dickert_mahs_parse_buffer( + SubGhzProtocolDecoderDickertMAHS* instance, + FuriString* output) { + // We assume we have only decodes < 64 bit! + uint64_t data = instance->generic.data; + uint8_t bits[36] = {}; + + // Convert uint64_t into bit array + for(int i = 35; i >= 0; i--) { + if(data & 1) { + bits[i] = 1; + } + data >>= 1; + } + + // Decode symbols + FuriString* code = furi_string_alloc(); + for(size_t i = 0; i < 35; i += 2) { + uint8_t dip = (bits[i] << 1) + bits[i + 1]; + // PLUS = 3, // 0b11 + // ZERO = 1, // 0b01 + // MINUS = 0, // 0x00 + if(dip == 0x01) { + furi_string_cat(code, "0"); + } else if(dip == 0x00) { + furi_string_cat(code, "-"); + } else if(dip == 0x03) { + furi_string_cat(code, "+"); + } else { + furi_string_cat(code, "?"); + } + } + + FuriString* user_dips = furi_string_alloc(); + FuriString* fact_dips = furi_string_alloc(); + furi_string_set_n(user_dips, code, 0, 10); + furi_string_set_n(fact_dips, code, 10, 8); + + furi_string_cat_printf( + output, + "%s\r\n" + "User-Dips:\t%s\r\n" + "Fac-Code:\t%s\r\n", + instance->generic.protocol_name, + furi_string_get_cstr(user_dips), + furi_string_get_cstr(fact_dips)); + furi_string_free(user_dips); + furi_string_free(fact_dips); + furi_string_free(code); +} + +void* subghz_protocol_encoder_dickert_mahs_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolEncoderDickertMAHS* instance = malloc(sizeof(SubGhzProtocolEncoderDickertMAHS)); + + instance->base.protocol = &subghz_protocol_dickert_mahs; + instance->generic.protocol_name = instance->base.protocol->name; + + instance->encoder.repeat = 10; + instance->encoder.size_upload = 128; + instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); + instance->encoder.is_running = false; + return instance; +} + +void subghz_protocol_encoder_dickert_mahs_free(void* context) { + furi_assert(context); + SubGhzProtocolEncoderDickertMAHS* instance = context; + free(instance->encoder.upload); + free(instance); +} + +/** + * Generating an upload from data. + * @param instance Pointer to a SubGhzProtocolEncoderDickertMAHS instance + * @return true On success + */ +static bool + subghz_protocol_encoder_dickert_mahs_get_upload(SubGhzProtocolEncoderDickertMAHS* instance) { + furi_assert(instance); + size_t index = 0; + size_t size_upload = (instance->generic.data_count_bit * 2) + 2; + if(size_upload > instance->encoder.size_upload) { + FURI_LOG_E(TAG, "Size upload exceeds allocated encoder buffer."); + return false; + } else { + instance->encoder.size_upload = size_upload; + } + + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_dickert_mahs_const.te_short * 112); + // Send start bit + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_dickert_mahs_const.te_short); + + //Send key data + for(uint8_t i = instance->generic.data_count_bit; i > 0; i--) { + if(bit_read(instance->generic.data, i - 1)) { + //send bit 1 + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_dickert_mahs_const.te_long); + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_dickert_mahs_const.te_short); + } else { + //send bit 0 + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_dickert_mahs_const.te_short); + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_dickert_mahs_const.te_long); + } + } + + return true; +} + +SubGhzProtocolStatus + subghz_protocol_encoder_dickert_mahs_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolEncoderDickertMAHS* instance = context; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; + do { + ret = subghz_block_generic_deserialize(&instance->generic, flipper_format); + if(ret != SubGhzProtocolStatusOk) { + break; + } + + // Allow for longer keys (<) instead of != + if((instance->generic.data_count_bit < + subghz_protocol_dickert_mahs_const.min_count_bit_for_found)) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = SubGhzProtocolStatusErrorValueBitCount; + break; + } + //optional parameter parameter + flipper_format_read_uint32( + flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); + + if(!subghz_protocol_encoder_dickert_mahs_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } + instance->encoder.is_running = true; + } while(false); + + return ret; +} + +void subghz_protocol_encoder_dickert_mahs_stop(void* context) { + SubGhzProtocolEncoderDickertMAHS* instance = context; + instance->encoder.is_running = false; +} + +LevelDuration subghz_protocol_encoder_dickert_mahs_yield(void* context) { + SubGhzProtocolEncoderDickertMAHS* instance = context; + + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; + return level_duration_reset(); + } + + LevelDuration ret = instance->encoder.upload[instance->encoder.front]; + + if(++instance->encoder.front == instance->encoder.size_upload) { + instance->encoder.repeat--; + instance->encoder.front = 0; + } + + return ret; +} + +void* subghz_protocol_decoder_dickert_mahs_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolDecoderDickertMAHS* instance = malloc(sizeof(SubGhzProtocolDecoderDickertMAHS)); + instance->base.protocol = &subghz_protocol_dickert_mahs; + instance->generic.protocol_name = instance->base.protocol->name; + instance->tmp_cnt = 0; + + return instance; +} + +void subghz_protocol_decoder_dickert_mahs_free(void* context) { + furi_assert(context); + SubGhzProtocolDecoderDickertMAHS* instance = context; + free(instance); +} + +void subghz_protocol_decoder_dickert_mahs_reset(void* context) { + furi_assert(context); + SubGhzProtocolDecoderDickertMAHS* instance = context; + instance->decoder.parser_step = DickertMAHSDecoderStepReset; +} + +void subghz_protocol_decoder_dickert_mahs_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + SubGhzProtocolDecoderDickertMAHS* instance = context; + + switch(instance->decoder.parser_step) { + case DickertMAHSDecoderStepReset: + // Check if done + if(instance->decoder.decode_count_bit >= + subghz_protocol_dickert_mahs_const.min_count_bit_for_found) { + instance->generic.serial = 0x0; + instance->generic.btn = 0x0; + + instance->generic.data = instance->decoder.decode_data; + instance->generic.data_count_bit = instance->decoder.decode_count_bit; + + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + } + + if((!level) && (duration > 10 * subghz_protocol_dickert_mahs_const.te_short)) { + //Found header DICKERT_MAHS + instance->decoder.parser_step = DickertMAHSDecoderStepInitial; + } + break; + case DickertMAHSDecoderStepInitial: + if(!level) { + break; + } else if( + DURATION_DIFF(duration, subghz_protocol_dickert_mahs_const.te_short) < + subghz_protocol_dickert_mahs_const.te_delta) { + //Found start bit DICKERT_MAHS + instance->decoder.parser_step = DickertMAHSDecoderStepRecording; + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + } else { + instance->decoder.parser_step = DickertMAHSDecoderStepReset; + } + break; + case DickertMAHSDecoderStepRecording: + if((!level && instance->tmp_cnt == 0) || (level && instance->tmp_cnt == 1)) { + instance->tmp[instance->tmp_cnt] = duration; + + instance->tmp_cnt++; + + if(instance->tmp_cnt == 2) { + if(DURATION_DIFF(instance->tmp[0] + instance->tmp[1], 1200) < + subghz_protocol_dickert_mahs_const.te_delta) { + if(DURATION_DIFF(instance->tmp[0], subghz_protocol_dickert_mahs_const.te_long) < + subghz_protocol_dickert_mahs_const.te_delta) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + } else if( + DURATION_DIFF( + instance->tmp[0], subghz_protocol_dickert_mahs_const.te_short) < + subghz_protocol_dickert_mahs_const.te_delta) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + } + + instance->tmp_cnt = 0; + } else { + instance->tmp_cnt = 0; + instance->decoder.parser_step = DickertMAHSDecoderStepReset; + } + } + } else { + instance->tmp_cnt = 0; + instance->decoder.parser_step = DickertMAHSDecoderStepReset; + } + + break; + } +} + +uint32_t subghz_protocol_decoder_dickert_mahs_get_hash_data(void* context) { + furi_assert(context); + SubGhzProtocolDecoderDickertMAHS* instance = context; + return subghz_protocol_blocks_get_hash_data_long( + &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); +} + +SubGhzProtocolStatus subghz_protocol_decoder_dickert_mahs_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset) { + furi_assert(context); + SubGhzProtocolDecoderDickertMAHS* instance = context; + return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); +} + +SubGhzProtocolStatus + subghz_protocol_decoder_dickert_mahs_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolDecoderDickertMAHS* instance = context; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; + do { + ret = subghz_block_generic_deserialize(&instance->generic, flipper_format); + if(ret != SubGhzProtocolStatusOk) { + break; + } + + // Allow for longer keys (<) instead of != + if((instance->generic.data_count_bit < + subghz_protocol_dickert_mahs_const.min_count_bit_for_found)) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = SubGhzProtocolStatusErrorValueBitCount; + break; + } + } while(false); + return ret; +} + +void subghz_protocol_decoder_dickert_mahs_get_string(void* context, FuriString* output) { + furi_assert(context); + subghz_protocol_encoder_dickert_mahs_parse_buffer(context, output); +} diff --git a/lib/subghz/protocols/dickert_mahs.h b/lib/subghz/protocols/dickert_mahs.h new file mode 100644 index 000000000..6051f243d --- /dev/null +++ b/lib/subghz/protocols/dickert_mahs.h @@ -0,0 +1,120 @@ +#pragma once + +#include "base.h" + +#define SUBGHZ_PROTOCOL_DICKERT_MAHS_NAME "Dickert_MAHS" + +typedef struct SubGhzProtocolDecoderDickertMAHS SubGhzProtocolDecoderDickertMAHS; +typedef struct SubGhzProtocolEncoderDickertMAHS SubGhzProtocolEncoderDickertMAHS; + +extern const SubGhzProtocolDecoder subghz_protocol_dickert_mahs_decoder; +extern const SubGhzProtocolEncoder subghz_protocol_dickert_mahs_encoder; +extern const SubGhzProtocol subghz_protocol_dickert_mahs; + +/** Allocate SubGhzProtocolEncoderDickertMAHS. + * + * @param environment Pointer to a SubGhzEnvironment instance + * + * @return pointer to a SubGhzProtocolEncoderDickertMAHS instance + */ +void* subghz_protocol_encoder_dickert_mahs_alloc(SubGhzEnvironment* environment); + +/** Free SubGhzProtocolEncoderDickertMAHS. + * + * @param context Pointer to a SubGhzProtocolEncoderDickertMAHS instance + */ +void subghz_protocol_encoder_dickert_mahs_free(void* context); + +/** Deserialize and generating an upload to send. + * + * @param context Pointer to a SubGhzProtocolEncoderDickertMAHS + * instance + * @param flipper_format Pointer to a FlipperFormat instance + * + * @return status + */ +SubGhzProtocolStatus + subghz_protocol_encoder_dickert_mahs_deserialize(void* context, FlipperFormat* flipper_format); + +/** Forced transmission stop. + * + * @param context Pointer to a SubGhzProtocolEncoderDickertMAHS instance + */ +void subghz_protocol_encoder_dickert_mahs_stop(void* context); + +/** Getting the level and duration of the upload to be loaded into DMA. + * + * @param context Pointer to a SubGhzProtocolEncoderDickertMAHS instance + * + * @return LevelDuration + */ +LevelDuration subghz_protocol_encoder_dickert_mahs_yield(void* context); + +/** Allocate SubGhzProtocolDecoderDickertMAHS. + * + * @param environment Pointer to a SubGhzEnvironment instance + * + * @return pointer to a SubGhzProtocolDecoderDickertMAHS instance + */ +void* subghz_protocol_decoder_dickert_mahs_alloc(SubGhzEnvironment* environment); + +/** Free SubGhzProtocolDecoderDickertMAHS. + * + * @param context Pointer to a SubGhzProtocolDecoderDickertMAHS instance + */ +void subghz_protocol_decoder_dickert_mahs_free(void* context); + +/** Reset decoder SubGhzProtocolDecoderDickertMAHS. + * + * @param context Pointer to a SubGhzProtocolDecoderDickertMAHS instance + */ +void subghz_protocol_decoder_dickert_mahs_reset(void* context); + +/** Parse a raw sequence of levels and durations received from the air. + * + * @param context Pointer to a SubGhzProtocolDecoderDickertMAHS instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void subghz_protocol_decoder_dickert_mahs_feed(void* context, bool level, uint32_t duration); + +/** Getting the hash sum of the last randomly received parcel. + * + * @param context Pointer to a SubGhzProtocolDecoderDickertMAHS instance + * + * @return hash Hash sum + */ +uint32_t subghz_protocol_decoder_dickert_mahs_get_hash_data(void* context); + +/** Serialize data SubGhzProtocolDecoderDickertMAHS. + * + * @param context Pointer to a SubGhzProtocolDecoderDickertMAHS + * instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param preset The modulation on which the signal was received, + * SubGhzRadioPreset + * + * @return status + */ +SubGhzProtocolStatus subghz_protocol_decoder_dickert_mahs_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset); + +/** Deserialize data SubGhzProtocolDecoderDickertMAHS. + * + * @param context Pointer to a SubGhzProtocolDecoderDickertMAHS + * instance + * @param flipper_format Pointer to a FlipperFormat instance + * + * @return status + */ +SubGhzProtocolStatus + subghz_protocol_decoder_dickert_mahs_deserialize(void* context, FlipperFormat* flipper_format); + +/** Getting a textual representation of the received data. + * + * @param context Pointer to a SubGhzProtocolDecoderDickertMAHS instance + * @param output Resulting text + */ +void subghz_protocol_decoder_dickert_mahs_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/protocol_items.c b/lib/subghz/protocols/protocol_items.c index 8275071eb..ca966390c 100644 --- a/lib/subghz/protocols/protocol_items.c +++ b/lib/subghz/protocols/protocol_items.c @@ -72,6 +72,7 @@ const SubGhzProtocol* subghz_protocol_registry_items[] = { &subghz_protocol_x10, &subghz_protocol_hormann_bisecur, &subghz_protocol_legrand, + &subghz_protocol_dickert_mahs, }; const SubGhzProtocolRegistry subghz_protocol_registry = { diff --git a/lib/subghz/protocols/protocol_items.h b/lib/subghz/protocols/protocol_items.h index 367025951..16dabf6b5 100644 --- a/lib/subghz/protocols/protocol_items.h +++ b/lib/subghz/protocols/protocol_items.h @@ -73,3 +73,4 @@ #include "x10.h" #include "hormann_bisecur.h" #include "legrand.h" +#include "dickert_mahs.h" diff --git a/lib/toolbox/api_lock.h b/lib/toolbox/api_lock.h index 5902a4922..a370514da 100644 --- a/lib/toolbox/api_lock.h +++ b/lib/toolbox/api_lock.h @@ -41,3 +41,7 @@ typedef FuriEventFlag* FuriApiLock; #define api_lock_wait_unlock_and_free(_lock) \ api_lock_wait_unlock(_lock); \ api_lock_free(_lock); + +#define api_lock_is_locked(_lock) (!(furi_event_flag_get(_lock) & API_LOCK_EVENT)) + +#define api_lock_relock(_lock) furi_event_flag_clear(_lock, API_LOCK_EVENT) diff --git a/lib/toolbox/crc32_calc.c b/lib/toolbox/crc32_calc.c index 78295167f..60d709a36 100644 --- a/lib/toolbox/crc32_calc.c +++ b/lib/toolbox/crc32_calc.c @@ -1,11 +1,37 @@ #include "crc32_calc.h" -#include #define CRC_DATA_BUFFER_MAX_LEN 512 uint32_t crc32_calc_buffer(uint32_t crc, const void* buffer, size_t size) { - // TODO FL-3547: consider removing dependency on LFS - return ~lfs_crc(~crc, buffer, size); + crc = ~crc; + + static const uint32_t rtable[16] = { + 0x00000000, + 0x1db71064, + 0x3b6e20c8, + 0x26d930ac, + 0x76dc4190, + 0x6b6b51f4, + 0x4db26158, + 0x5005713c, + 0xedb88320, + 0xf00f9344, + 0xd6d6a3e8, + 0xcb61b38c, + 0x9b64c2b0, + 0x86d3d2d4, + 0xa00ae278, + 0xbdbdf21c, + }; + + const uint8_t* data = buffer; + + for(size_t i = 0; i < size; i++) { + crc = (crc >> 4) ^ rtable[(crc ^ (data[i] >> 0)) & 0xf]; + crc = (crc >> 4) ^ rtable[(crc ^ (data[i] >> 4)) & 0xf]; + } + + return ~crc; } uint32_t crc32_calc_file(File* file, const FileCrcProgressCb progress_cb, void* context) { diff --git a/lib/toolbox/run_parallel.c b/lib/toolbox/run_parallel.c new file mode 100644 index 000000000..fbb727129 --- /dev/null +++ b/lib/toolbox/run_parallel.c @@ -0,0 +1,26 @@ +#include "run_parallel.h" + +#include +#include + +static void run_parallel_pending_callback(void* context, uint32_t arg) { + UNUSED(arg); + + FuriThread* thread = context; + furi_thread_join(thread); + furi_thread_free(thread); +} + +static void run_parallel_thread_state(FuriThreadState state, void* context) { + UNUSED(context); + + if(state == FuriThreadStateStopped) { + furi_timer_pending_callback(run_parallel_pending_callback, furi_thread_get_current(), 0); + } +} + +void run_parallel(FuriThreadCallback callback, void* context, uint32_t stack_size) { + FuriThread* thread = furi_thread_alloc_ex(NULL, stack_size, callback, context); + furi_thread_set_state_callback(thread, run_parallel_thread_state); + furi_thread_start(thread); +} diff --git a/lib/toolbox/run_parallel.h b/lib/toolbox/run_parallel.h new file mode 100644 index 000000000..2722c54eb --- /dev/null +++ b/lib/toolbox/run_parallel.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +/** + * @brief Run function in thread, then automatically clean up thread. + * + * @param[in] callback pointer to a function to be executed in parallel + * @param[in] context pointer to a user-specified object (will be passed to the callback) + * @param[in] stack_size stack size in bytes + */ +void run_parallel(FuriThreadCallback callback, void* context, uint32_t stack_size); diff --git a/lib/toolbox/stream/file_stream.c b/lib/toolbox/stream/file_stream.c index 80cbb7d5f..a0dfda3eb 100644 --- a/lib/toolbox/stream/file_stream.c +++ b/lib/toolbox/stream/file_stream.c @@ -159,8 +159,8 @@ static bool file_stream_delete_and_insert( FuriString* tmp_name; tmp_name = furi_string_alloc(); storage_get_next_filename( - _stream->storage, STORAGE_ANY_PATH_PREFIX, ".scratch", ".pad", tmp_name, 255); - scratch_name = furi_string_alloc_printf(ANY_PATH("%s.pad"), furi_string_get_cstr(tmp_name)); + _stream->storage, STORAGE_EXT_PATH_PREFIX, ".scratch", ".pad", tmp_name, 255); + scratch_name = furi_string_alloc_printf(EXT_PATH("%s.pad"), furi_string_get_cstr(tmp_name)); furi_string_free(tmp_name); do { diff --git a/lib/toolbox/tar/tar_archive.c b/lib/toolbox/tar/tar_archive.c index 9b4f18878..437c53a33 100644 --- a/lib/toolbox/tar/tar_archive.c +++ b/lib/toolbox/tar/tar_archive.c @@ -19,15 +19,18 @@ TarOpenMode tar_archive_get_mode_for_path(const char* path) { FuriString* path_str = furi_string_alloc_set_str(path); path_extract_extension(path_str, ext, sizeof(ext)); - furi_string_free(path_str); + TarOpenMode open_mode; if(strcmp(ext, ".ths") == 0) { - return TarOpenModeReadHeatshrink; - } else if(strcmp(ext, ".tgz") == 0) { - return TarOpenModeReadGzip; + open_mode = TarOpenModeReadHeatshrink; + } else if(strcmp(ext, ".tgz") == 0 || furi_string_end_with(path_str, ".tar.gz")) { + open_mode = TarOpenModeReadGzip; } else { - return TarOpenModeRead; + open_mode = TarOpenModeRead; } + + furi_string_free(path_str); + return open_mode; } typedef struct TarArchive { @@ -325,7 +328,7 @@ bool tar_archive_file_finalize(TarArchive* archive) { typedef struct { TarArchive* archive; const char* work_dir; - Storage_name_converter converter; + TarArchiveNameConverter converter; } TarArchiveDirectoryOpParams; static bool archive_extract_current_file(TarArchive* archive, const char* dst_path) { @@ -429,7 +432,7 @@ static int archive_extract_foreach_cb(mtar_t* tar, const mtar_header_t* header, bool tar_archive_unpack_to( TarArchive* archive, const char* destination, - Storage_name_converter converter) { + TarArchiveNameConverter converter) { furi_check(archive); TarArchiveDirectoryOpParams param = { .archive = archive, diff --git a/lib/toolbox/tar/tar_archive.h b/lib/toolbox/tar/tar_archive.h index 0858627b7..593c00c72 100644 --- a/lib/toolbox/tar/tar_archive.h +++ b/lib/toolbox/tar/tar_archive.h @@ -55,6 +55,8 @@ bool tar_archive_open(TarArchive* archive, const char* path, TarOpenMode mode); */ void tar_archive_free(TarArchive* archive); +typedef void (*TarArchiveNameConverter)(FuriString*); + /* High-level API - assumes archive is open */ /** Unpack tar archive to destination @@ -68,7 +70,7 @@ void tar_archive_free(TarArchive* archive); bool tar_archive_unpack_to( TarArchive* archive, const char* destination, - Storage_name_converter converter); + TarArchiveNameConverter converter); /** Add file to tar archive * diff --git a/scripts/flipper/assets/tarball.py b/scripts/flipper/assets/tarball.py index 28a5160d3..03b2d927f 100644 --- a/scripts/flipper/assets/tarball.py +++ b/scripts/flipper/assets/tarball.py @@ -9,7 +9,7 @@ from .heatshrink_stream import HeatshrinkDataStreamHeader FLIPPER_TAR_FORMAT = tarfile.USTAR_FORMAT TAR_HEATSHRINK_EXTENSION = ".ths" -TAR_GZIP_EXTENSION = ".tgz" +TAR_GZIP_EXTENSION = ".tar.gz" def tar_sanitizer_filter(tarinfo: tarfile.TarInfo): diff --git a/scripts/imglint.py b/scripts/imglint.py new file mode 100644 index 000000000..7325343ac --- /dev/null +++ b/scripts/imglint.py @@ -0,0 +1,102 @@ +import logging +import multiprocessing +import os +from pathlib import Path + +from flipper.app import App +from PIL import Image + +_logger = logging.getLogger(__name__) + + +def _check_image(image, do_fixup=False): + failed_checks = [] + with Image.open(image) as img: + # check that is's pure 1-bit B&W + if img.mode != "1": + failed_checks.append(f"not 1-bit B&W, but {img.mode}") + if do_fixup: + img = img.convert("1") + + # ...and does not have any metadata or ICC profile + if img.info: + failed_checks.append(f"has metadata") + if do_fixup: + img.info = {} + + if do_fixup: + img.save(image) + _logger.info(f"Fixed image {image}") + + if failed_checks: + _logger.warning(f"Image {image} issues: {'; '.join(failed_checks)}") + return len(failed_checks) == 0 + + +class ImageLint(App): + ICONS_SUPPORTED_FORMATS = [".png"] + + def init(self): + self.subparsers = self.parser.add_subparsers(help="sub-command help") + + self.parser_check = self.subparsers.add_parser( + "check", help="Check image format and file names" + ) + self.parser_check.add_argument("input", nargs="+") + self.parser_check.set_defaults(func=self.check) + + self.parser_format = self.subparsers.add_parser( + "format", help="Format image and fix file names" + ) + self.parser_format.add_argument( + "input", + nargs="+", + ) + self.parser_format.set_defaults(func=self.format) + + def _gather_images(self, folders): + images = [] + for folder in folders: + exclude = folder.startswith("!") + for dirpath, _, filenames in os.walk(folder.removeprefix("!")): + for filename in filenames: + if self.is_file_an_icon(filename): + filepath = os.path.join(dirpath, filename) + if exclude: + images.remove(filepath) + else: + images.append(filepath) + return images + + def is_file_an_icon(self, filename): + extension = Path(filename).suffix.lower() + return extension in self.ICONS_SUPPORTED_FORMATS + + def _process_images(self, images, do_fixup): + with multiprocessing.Pool() as pool: + image_checks = pool.starmap( + _check_image, [(image, do_fixup) for image in images] + ) + return all(image_checks) + + def check(self): + images = self._gather_images(self.args.input) + self.logger.info(f"Found {len(images)} images") + if not self._process_images(images, False): + self.logger.error("Some images are not in the correct format") + return 1 + self.logger.info("All images are in the correct format") + return 0 + + def format(self): + images = self._gather_images(self.args.input) + self.logger.info(f"Found {len(images)} images") + if not self._process_images(images, True): + self.logger.warning("Applied fixes to some images") + else: + self.logger.info("All images were in the correct format") + return 0 + + +if __name__ == "__main__": + ImageLint()() diff --git a/scripts/testops.py b/scripts/testops.py index bf02feaad..4ae10c7f4 100644 --- a/scripts/testops.py +++ b/scripts/testops.py @@ -39,7 +39,9 @@ class Main(App): if port := resolve_port(self.logger, self.args.port): self.logger.info(f"Found flipper at {port}") + time.sleep(1) break + time.sleep(1) if not port: diff --git a/scripts/update.py b/scripts/update.py index 2297cff99..641295371 100755 --- a/scripts/update.py +++ b/scripts/update.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 -import io import math import os import shutil @@ -9,7 +8,6 @@ import zlib from os.path import exists, join import pathlib -import heatshrink2 from flipper.app import App from flipper.assets.coprobin import CoproBinary, get_stack_type from flipper.assets.heatshrink_stream import HeatshrinkDataStreamHeader @@ -36,7 +34,12 @@ class Main(App): ) FLASH_BASE = 0x8000000 - MIN_LFS_PAGES = 6 + FLASH_PAGE_SIZE = 4 * 1024 + MIN_GAP_PAGES = 2 + + # Update stage file larger than that is not loadable without fix + # https://github.com/flipperdevices/flipperzero-firmware/pull/3676 + UPDATER_SIZE_THRESHOLD = 128 * 1024 HEATSHRINK_WINDOW_SIZE = 13 HEATSHRINK_LOOKAHEAD_SIZE = 6 @@ -118,7 +121,7 @@ class Main(App): self.logger.error( f"You are trying to bundle a non-standard stack type '{self.args.radiotype}'." ) - self.disclaimer() + self.show_disclaimer() return 1 if radio_addr == 0: @@ -131,14 +134,9 @@ class Main(App): if not exists(self.args.directory): os.makedirs(self.args.directory) - stage_size = os.stat(self.args.stage).st_size - max_stage_size = 131072 # 2 * MAX_READ in src/update.c - if stage_size > max_stage_size: - self.logger.warn( - f"RAM {stage_basename} size too big ({stage_size} > {max_stage_size} bytes)" - ) - return 2 + updater_stage_size = os.stat(self.args.stage).st_size shutil.copyfile(self.args.stage, join(self.args.directory, stage_basename)) + dfu_size = 0 if self.args.dfu: dfu_size = os.stat(self.args.dfu).st_size @@ -165,10 +163,10 @@ class Main(App): ): return 3 - if not self.layout_check(dfu_size, radio_addr): + if not self.layout_check(updater_stage_size, dfu_size, radio_addr): self.logger.warn("Memory layout looks suspicious") - if not self.args.disclaimer == "yes": - self.disclaimer() + if self.args.disclaimer != "yes": + self.show_disclaimer() return 2 if self.args.splash: @@ -225,22 +223,33 @@ class Main(App): return 0 - def layout_check(self, fw_size, radio_addr): + def layout_check(self, stage_size, fw_size, radio_addr): + if stage_size > self.UPDATER_SIZE_THRESHOLD: + self.logger.warn( + f"Updater size {stage_size}b > {self.UPDATER_SIZE_THRESHOLD}b and is not loadable on older firmwares!" + ) + if fw_size == 0 or radio_addr == 0: self.logger.info("Cannot validate layout for partial package") return True - lfs_span = radio_addr - self.FLASH_BASE - fw_size - self.logger.debug(f"Expected LFS size: {lfs_span}") - lfs_span_pages = lfs_span / (4 * 1024) - if lfs_span_pages < self.MIN_LFS_PAGES: + fw2stack_gap = radio_addr - self.FLASH_BASE - fw_size + self.logger.debug(f"Expected reserved space size: {fw2stack_gap}") + fw2stack_gap_pages = fw2stack_gap / self.FLASH_PAGE_SIZE + if fw2stack_gap_pages < 0: self.logger.warn( - f"Expected LFS size is too small (~{int(lfs_span_pages)} pages)" + f"Firmware image overlaps C2 region and is not programmable!" + ) + return False + + elif fw2stack_gap_pages < self.MIN_GAP_PAGES: + self.logger.warn( + f"Expected reserved flash size is too small (~{int(fw2stack_gap_pages)} page(s), need >={self.MIN_GAP_PAGES} page(s))" ) return False return True - def disclaimer(self): + def show_disclaimer(self): self.logger.error( "You might brick your device into a state in which you'd need an SWD programmer to fix it." ) diff --git a/targets/f18/api_symbols.csv b/targets/f18/api_symbols.csv index 7e254ce40..4745dc956 100644 --- a/targets/f18/api_symbols.csv +++ b/targets/f18/api_symbols.csv @@ -13,6 +13,7 @@ Header,+,applications/services/gui/icon_i.h,, Header,+,applications/services/gui/modules/button_menu.h,, Header,+,applications/services/gui/modules/button_panel.h,, Header,+,applications/services/gui/modules/byte_input.h,, +Header,+,applications/services/gui/modules/number_input.h,, Header,+,applications/services/gui/modules/dialog_ex.h,, Header,+,applications/services/gui/modules/empty_screen.h,, Header,+,applications/services/gui/modules/file_browser.h,, @@ -687,6 +688,7 @@ Function,+,bt_forget_bonded_devices,void,Bt* Function,+,bt_keys_storage_alloc,BtKeysStorage*,const char* Function,+,bt_keys_storage_delete,_Bool,BtKeysStorage* Function,+,bt_keys_storage_free,void,BtKeysStorage* +Function,+,bt_keys_storage_is_changed,_Bool,BtKeysStorage* Function,+,bt_keys_storage_load,_Bool,BtKeysStorage* Function,+,bt_keys_storage_set_default_path,void,Bt* Function,+,bt_keys_storage_set_file_path,void,"BtKeysStorage*, const char*" @@ -721,6 +723,11 @@ Function,+,byte_input_free,void,ByteInput* Function,+,byte_input_get_view,View*,ByteInput* Function,+,byte_input_set_header_text,void,"ByteInput*, const char*" Function,+,byte_input_set_result_callback,void,"ByteInput*, ByteInputCallback, ByteChangedCallback, void*, uint8_t*, uint8_t" +Function,+,number_input_alloc,NumberInput*, +Function,+,number_input_free,void,NumberInput* +Function,+,number_input_get_view,View*,NumberInput* +Function,+,number_input_set_header_text,void,"NumberInput*, const char*" +Function,+,number_input_set_result_callback,void,"NumberInput*, NumberInputCallback, void*, int32_t, int32_t, int32_t" Function,-,bzero,void,"void*, size_t" Function,+,calloc,void*,"size_t, size_t" Function,+,canvas_clear,void,Canvas* @@ -1107,11 +1114,13 @@ Function,+,furi_event_flag_set,uint32_t,"FuriEventFlag*, uint32_t" Function,+,furi_event_flag_wait,uint32_t,"FuriEventFlag*, uint32_t, uint32_t, uint32_t" Function,+,furi_event_loop_alloc,FuriEventLoop*, Function,+,furi_event_loop_free,void,FuriEventLoop* -Function,+,furi_event_loop_message_queue_subscribe,void,"FuriEventLoop*, FuriMessageQueue*, FuriEventLoopEvent, FuriEventLoopMessageQueueCallback, void*" -Function,+,furi_event_loop_message_queue_unsubscribe,void,"FuriEventLoop*, FuriMessageQueue*" Function,+,furi_event_loop_pend_callback,void,"FuriEventLoop*, FuriEventLoopPendingCallback, void*" Function,+,furi_event_loop_run,void,FuriEventLoop* Function,+,furi_event_loop_stop,void,FuriEventLoop* +Function,+,furi_event_loop_subscribe_message_queue,void,"FuriEventLoop*, FuriMessageQueue*, FuriEventLoopEvent, FuriEventLoopEventCallback, void*" +Function,+,furi_event_loop_subscribe_mutex,void,"FuriEventLoop*, FuriMutex*, FuriEventLoopEvent, FuriEventLoopEventCallback, void*" +Function,+,furi_event_loop_subscribe_semaphore,void,"FuriEventLoop*, FuriSemaphore*, FuriEventLoopEvent, FuriEventLoopEventCallback, void*" +Function,+,furi_event_loop_subscribe_stream_buffer,void,"FuriEventLoop*, FuriStreamBuffer*, FuriEventLoopEvent, FuriEventLoopEventCallback, void*" Function,+,furi_event_loop_tick_set,void,"FuriEventLoop*, uint32_t, FuriEventLoopTickCallback, void*" Function,+,furi_event_loop_timer_alloc,FuriEventLoopTimer*,"FuriEventLoop*, FuriEventLoopTimerCallback, FuriEventLoopTimerType, void*" Function,+,furi_event_loop_timer_free,void,FuriEventLoopTimer* @@ -1121,6 +1130,7 @@ Function,+,furi_event_loop_timer_is_running,_Bool,const FuriEventLoopTimer* Function,+,furi_event_loop_timer_restart,void,FuriEventLoopTimer* Function,+,furi_event_loop_timer_start,void,"FuriEventLoopTimer*, uint32_t" Function,+,furi_event_loop_timer_stop,void,FuriEventLoopTimer* +Function,+,furi_event_loop_unsubscribe,void,"FuriEventLoop*, FuriEventLoopObject*" Function,+,furi_get_tick,uint32_t, Function,+,furi_hal_adc_acquire,FuriHalAdcHandle*, Function,+,furi_hal_adc_configure,void,FuriHalAdcHandle* @@ -1372,6 +1382,7 @@ Function,+,furi_hal_rtc_get_log_baud_rate,FuriHalRtcLogBaudRate, Function,+,furi_hal_rtc_get_log_device,FuriHalRtcLogDevice, Function,+,furi_hal_rtc_get_log_level,uint8_t, Function,+,furi_hal_rtc_get_pin_fails,uint32_t, +Function,-,furi_hal_rtc_get_pin_value,uint32_t, Function,+,furi_hal_rtc_get_register,uint32_t,FuriHalRtcRegister Function,+,furi_hal_rtc_get_timestamp,uint32_t, Function,-,furi_hal_rtc_init,void, @@ -1391,6 +1402,7 @@ Function,+,furi_hal_rtc_set_log_baud_rate,void,FuriHalRtcLogBaudRate Function,+,furi_hal_rtc_set_log_device,void,FuriHalRtcLogDevice Function,+,furi_hal_rtc_set_log_level,void,uint8_t Function,+,furi_hal_rtc_set_pin_fails,void,uint32_t +Function,-,furi_hal_rtc_set_pin_value,void,uint32_t Function,+,furi_hal_rtc_set_register,void,"FuriHalRtcRegister, uint32_t" Function,+,furi_hal_rtc_sync_shadow,void, Function,+,furi_hal_sd_get_card_state,FuriStatus, @@ -1541,6 +1553,7 @@ Function,+,furi_semaphore_acquire,FuriStatus,"FuriSemaphore*, uint32_t" Function,+,furi_semaphore_alloc,FuriSemaphore*,"uint32_t, uint32_t" Function,+,furi_semaphore_free,void,FuriSemaphore* Function,+,furi_semaphore_get_count,uint32_t,FuriSemaphore* +Function,+,furi_semaphore_get_space,uint32_t,FuriSemaphore* Function,+,furi_semaphore_release,FuriStatus,FuriSemaphore* Function,+,furi_stream_buffer_alloc,FuriStreamBuffer*,"size_t, size_t" Function,+,furi_stream_buffer_bytes_available,size_t,FuriStreamBuffer* @@ -1569,6 +1582,8 @@ Function,+,furi_string_cmpi_str,int,"const FuriString*, const char[]" Function,+,furi_string_empty,_Bool,const FuriString* Function,+,furi_string_end_with,_Bool,"const FuriString*, const FuriString*" Function,+,furi_string_end_with_str,_Bool,"const FuriString*, const char[]" +Function,+,furi_string_end_withi,_Bool,"const FuriString*, const FuriString*" +Function,+,furi_string_end_withi_str,_Bool,"const FuriString*, const char[]" Function,+,furi_string_equal,_Bool,"const FuriString*, const FuriString*" Function,+,furi_string_equal_str,_Bool,"const FuriString*, const char[]" Function,+,furi_string_free,void,FuriString* @@ -1626,6 +1641,7 @@ Function,+,furi_thread_get_id,FuriThreadId,FuriThread* Function,+,furi_thread_get_name,const char*,FuriThreadId Function,+,furi_thread_get_priority,FuriThreadPriority,FuriThread* Function,+,furi_thread_get_return_code,int32_t,FuriThread* +Function,+,furi_thread_get_signal_callback,FuriThreadSignalCallback,const FuriThread* Function,+,furi_thread_get_stack_space,uint32_t,FuriThreadId Function,+,furi_thread_get_state,FuriThreadState,FuriThread* Function,+,furi_thread_get_stdout_callback,FuriThreadStdoutWriteCallback, @@ -2278,7 +2294,7 @@ Function,+,power_get_info,void,"Power*, PowerInfo*" Function,+,power_get_pubsub,FuriPubSub*,Power* Function,+,power_is_battery_healthy,_Bool,Power* Function,+,power_off,void,Power* -Function,+,power_reboot,void,PowerBootMode +Function,+,power_reboot,void,"Power*, PowerBootMode" Function,+,powf,float,"float, float" Function,-,powl,long double,"long double, long double" Function,+,pretty_format_bytes_hex_canonical,void,"FuriString*, size_t, const char*, const uint8_t*, size_t" @@ -2509,7 +2525,7 @@ Function,+,storage_file_write,size_t,"File*, const void*, size_t" Function,+,storage_get_next_filename,void,"Storage*, const char*, const char*, const char*, FuriString*, uint8_t" Function,+,storage_get_pubsub,FuriPubSub*,Storage* Function,+,storage_int_backup,FS_Error,"Storage*, const char*" -Function,+,storage_int_restore,FS_Error,"Storage*, const char*, Storage_name_converter" +Function,+,storage_int_restore,FS_Error,"Storage*, const char*, StorageNameConverter" Function,+,storage_sd_format,FS_Error,Storage* Function,+,storage_sd_info,FS_Error,"Storage*, SDInfo*" Function,+,storage_sd_mount,FS_Error,Storage* @@ -2641,7 +2657,7 @@ Function,+,tar_archive_open,_Bool,"TarArchive*, const char*, TarOpenMode" Function,+,tar_archive_set_file_callback,void,"TarArchive*, tar_unpack_file_cb, void*" Function,+,tar_archive_store_data,_Bool,"TarArchive*, const char*, const uint8_t*, const int32_t" Function,+,tar_archive_unpack_file,_Bool,"TarArchive*, const char*, const char*" -Function,+,tar_archive_unpack_to,_Bool,"TarArchive*, const char*, Storage_name_converter" +Function,+,tar_archive_unpack_to,_Bool,"TarArchive*, const char*, TarArchiveNameConverter" Function,-,tempnam,char*,"const char*, const char*" Function,+,text_box_alloc,TextBox*, Function,+,text_box_free,void,TextBox* @@ -2753,11 +2769,11 @@ Function,+,view_holder_alloc,ViewHolder*, Function,+,view_holder_attach_to_gui,void,"ViewHolder*, Gui*" Function,+,view_holder_free,void,ViewHolder* Function,+,view_holder_get_free_context,void*,ViewHolder* +Function,+,view_holder_send_to_back,void,ViewHolder* +Function,+,view_holder_send_to_front,void,ViewHolder* Function,+,view_holder_set_back_callback,void,"ViewHolder*, BackCallback, void*" Function,+,view_holder_set_free_callback,void,"ViewHolder*, FreeCallback, void*" Function,+,view_holder_set_view,void,"ViewHolder*, View*" -Function,+,view_holder_start,void,ViewHolder* -Function,+,view_holder_stop,void,ViewHolder* Function,+,view_holder_update,void,"View*, void*" Function,+,view_port_alloc,ViewPort*, Function,+,view_port_draw_callback_set,void,"ViewPort*, ViewPortDrawCallback, void*" diff --git a/targets/f18/target.json b/targets/f18/target.json index 229ec0a7a..3452c6707 100644 --- a/targets/f18/target.json +++ b/targets/f18/target.json @@ -17,13 +17,11 @@ "stm32wb", "hwdrivers", "fatfs", - "littlefs", "toolbox", "digital_signal", "signal_reader", "microtar", "usb_stm32", - "appframe", "assets", "one_wire", "music_worker", diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index 9873b50ea..d4ff4489b 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -6,16 +6,11 @@ Header,+,applications/main/subghz/subghz_fap.h,, Header,+,applications/services/applications.h,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/bt/bt_service/bt_keys_storage.h,, -Header,+,applications/services/bt/bt_settings.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, -Header,+,applications/services/desktop/desktop_settings.h,, Header,+,applications/services/dialogs/dialogs.h,, Header,+,applications/services/dolphin/dolphin.h,, -Header,+,applications/services/dolphin/helpers/dolphin_state.h,, Header,+,applications/services/expansion/expansion.h,, -Header,+,applications/services/expansion/expansion_i.h,, -Header,+,applications/services/expansion/expansion_settings.h,, Header,+,applications/services/gui/elements.h,, Header,+,applications/services/gui/gui.h,, Header,+,applications/services/gui/icon_i.h,, @@ -28,6 +23,7 @@ Header,+,applications/services/gui/modules/file_browser.h,, Header,+,applications/services/gui/modules/file_browser_worker.h,, Header,+,applications/services/gui/modules/loading.h,, Header,+,applications/services/gui/modules/menu.h,, +Header,+,applications/services/gui/modules/number_input.h,, Header,+,applications/services/gui/modules/popup.h,, Header,+,applications/services/gui/modules/submenu.h,, Header,+,applications/services/gui/modules/text_box.h,, @@ -44,10 +40,8 @@ Header,+,applications/services/loader/firmware_api/firmware_api.h,, Header,+,applications/services/loader/loader.h,, Header,+,applications/services/locale/locale.h,, Header,+,applications/services/notification/notification.h,, -Header,+,applications/services/notification/notification_app.h,, Header,+,applications/services/notification/notification_messages.h,, Header,+,applications/services/power/power_service/power.h,, -Header,+,applications/services/power/power_settings.h,, Header,+,applications/services/rpc/rpc_app.h,, Header,+,applications/services/storage/storage.h,, Header,+,build/icons/assets_icons.h,, @@ -319,10 +313,6 @@ Header,+,targets/furi_hal_include/furi_hal_usb_hid.h,, Header,+,targets/furi_hal_include/furi_hal_usb_hid_u2f.h,, Header,+,targets/furi_hal_include/furi_hal_version.h,, Header,+,targets/furi_hal_include/furi_hal_vibro.h,, -Function,+,DESKTOP_KEYBINDS_LOAD,_Bool,"Keybinds*, size_t" -Function,+,DESKTOP_KEYBINDS_SAVE,_Bool,"Keybinds*, size_t" -Function,-,DESKTOP_SETTINGS_LOAD,_Bool,DesktopSettings* -Function,+,DESKTOP_SETTINGS_SAVE,_Bool,DesktopSettings* Function,-,LL_ADC_CommonDeInit,ErrorStatus,ADC_Common_TypeDef* Function,-,LL_ADC_CommonInit,ErrorStatus,"ADC_Common_TypeDef*, const LL_ADC_CommonInitTypeDef*" Function,-,LL_ADC_CommonStructInit,void,LL_ADC_CommonInitTypeDef* @@ -420,11 +410,9 @@ Function,-,LL_USART_DeInit,ErrorStatus,const USART_TypeDef* Function,+,LL_USART_Init,ErrorStatus,"USART_TypeDef*, const LL_USART_InitTypeDef*" Function,-,LL_USART_StructInit,void,LL_USART_InitTypeDef* Function,-,LL_mDelay,void,uint32_t -Function,+,LOAD_POWER_SETTINGS,_Bool,uint32_t* Function,-,Osal_MemCmp,int,"const void*, const void*, unsigned int" Function,-,Osal_MemCpy,void*,"void*, const void*, unsigned int" Function,-,Osal_MemSet,void*,"void*, int, unsigned int" -Function,+,SAVE_POWER_SETTINGS,_Bool,uint32_t* Function,-,SK6805_get_led_count,uint8_t, Function,-,SK6805_init,void, Function,-,SK6805_set_led_color,void,"uint8_t, uint8_t, uint8_t, uint8_t" @@ -793,6 +781,7 @@ Function,+,bt_forget_bonded_devices,void,Bt* Function,+,bt_keys_storage_alloc,BtKeysStorage*,const char* Function,+,bt_keys_storage_delete,_Bool,BtKeysStorage* Function,+,bt_keys_storage_free,void,BtKeysStorage* +Function,+,bt_keys_storage_is_changed,_Bool,BtKeysStorage* Function,+,bt_keys_storage_load,_Bool,BtKeysStorage* Function,+,bt_keys_storage_set_default_path,void,Bt* Function,+,bt_keys_storage_set_file_path,void,"BtKeysStorage*, const char*" @@ -804,8 +793,6 @@ Function,+,bt_profile_restore_default,_Bool,Bt* Function,+,bt_profile_start,FuriHalBleProfileBase*,"Bt*, const FuriHalBleProfileTemplate*, FuriHalBleProfileParams" Function,+,bt_remote_rssi,_Bool,"Bt*, uint8_t*" Function,+,bt_set_status_changed_callback,void,"Bt*, BtStatusChangedCallback, void*" -Function,-,bt_settings_load,_Bool,BtSettings* -Function,+,bt_settings_save,_Bool,const BtSettings* Function,+,buffered_file_stream_alloc,Stream*,Storage* Function,+,buffered_file_stream_close,_Bool,Stream* Function,+,buffered_file_stream_get_error,FS_Error,Stream* @@ -987,20 +974,8 @@ Function,+,dolphin_deed_get_app,DolphinApp,DolphinDeed Function,+,dolphin_deed_get_app_limit,uint8_t,DolphinApp Function,+,dolphin_deed_get_weight,uint8_t,DolphinDeed Function,+,dolphin_flush,void,Dolphin* -Function,+,dolphin_get_level,uint8_t,uint32_t Function,+,dolphin_get_pubsub,FuriPubSub*,Dolphin* -Function,+,dolphin_state_alloc,DolphinState*, -Function,+,dolphin_state_butthurted,void,DolphinState* -Function,+,dolphin_state_clear_limits,void,DolphinState* -Function,+,dolphin_state_free,void,DolphinState* -Function,+,dolphin_state_increase_level,void,DolphinState* -Function,+,dolphin_state_is_levelup,_Bool,uint32_t -Function,+,dolphin_state_load,_Bool,DolphinState* -Function,+,dolphin_state_on_deed,void,"DolphinState*, DolphinDeed" -Function,+,dolphin_state_save,_Bool,DolphinState* -Function,+,dolphin_state_timestamp,uint64_t, -Function,+,dolphin_state_xp_above_last_levelup,uint32_t,uint32_t -Function,+,dolphin_state_xp_to_levelup,uint32_t,uint32_t +Function,+,dolphin_reload_state,void,Dolphin* Function,+,dolphin_stats,DolphinStats,Dolphin* Function,+,dolphin_upgrade_level,void,Dolphin* Function,-,dprintf,int,"int, const char*, ..." @@ -1069,11 +1044,8 @@ Function,-,exp2f,float,float Function,-,exp2l,long double,long double Function,+,expansion_disable,void,Expansion* Function,+,expansion_enable,void,Expansion* -Function,+,expansion_get_settings,ExpansionSettings*,Expansion* Function,+,expansion_is_connected,_Bool,Expansion* Function,+,expansion_set_listen_serial,void,"Expansion*, FuriHalSerialId" -Function,-,expansion_settings_load,_Bool,ExpansionSettings* -Function,+,expansion_settings_save,_Bool,const ExpansionSettings* Function,-,expf,float,float Function,-,expl,long double,long double Function,-,explicit_bzero,void,"void*, size_t" @@ -1292,11 +1264,13 @@ Function,+,furi_event_flag_set,uint32_t,"FuriEventFlag*, uint32_t" Function,+,furi_event_flag_wait,uint32_t,"FuriEventFlag*, uint32_t, uint32_t, uint32_t" Function,+,furi_event_loop_alloc,FuriEventLoop*, Function,+,furi_event_loop_free,void,FuriEventLoop* -Function,+,furi_event_loop_message_queue_subscribe,void,"FuriEventLoop*, FuriMessageQueue*, FuriEventLoopEvent, FuriEventLoopMessageQueueCallback, void*" -Function,+,furi_event_loop_message_queue_unsubscribe,void,"FuriEventLoop*, FuriMessageQueue*" Function,+,furi_event_loop_pend_callback,void,"FuriEventLoop*, FuriEventLoopPendingCallback, void*" Function,+,furi_event_loop_run,void,FuriEventLoop* Function,+,furi_event_loop_stop,void,FuriEventLoop* +Function,+,furi_event_loop_subscribe_message_queue,void,"FuriEventLoop*, FuriMessageQueue*, FuriEventLoopEvent, FuriEventLoopEventCallback, void*" +Function,+,furi_event_loop_subscribe_mutex,void,"FuriEventLoop*, FuriMutex*, FuriEventLoopEvent, FuriEventLoopEventCallback, void*" +Function,+,furi_event_loop_subscribe_semaphore,void,"FuriEventLoop*, FuriSemaphore*, FuriEventLoopEvent, FuriEventLoopEventCallback, void*" +Function,+,furi_event_loop_subscribe_stream_buffer,void,"FuriEventLoop*, FuriStreamBuffer*, FuriEventLoopEvent, FuriEventLoopEventCallback, void*" Function,+,furi_event_loop_tick_set,void,"FuriEventLoop*, uint32_t, FuriEventLoopTickCallback, void*" Function,+,furi_event_loop_timer_alloc,FuriEventLoopTimer*,"FuriEventLoop*, FuriEventLoopTimerCallback, FuriEventLoopTimerType, void*" Function,+,furi_event_loop_timer_free,void,FuriEventLoopTimer* @@ -1306,6 +1280,7 @@ Function,+,furi_event_loop_timer_is_running,_Bool,const FuriEventLoopTimer* Function,+,furi_event_loop_timer_restart,void,FuriEventLoopTimer* Function,+,furi_event_loop_timer_start,void,"FuriEventLoopTimer*, uint32_t" Function,+,furi_event_loop_timer_stop,void,FuriEventLoopTimer* +Function,+,furi_event_loop_unsubscribe,void,"FuriEventLoop*, FuriEventLoopObject*" Function,+,furi_get_tick,uint32_t, Function,+,furi_hal_adc_acquire,FuriHalAdcHandle*, Function,+,furi_hal_adc_configure,void,FuriHalAdcHandle* @@ -1413,12 +1388,12 @@ Function,+,furi_hal_dma_init_early,void, Function,-,furi_hal_flash_erase,void,uint8_t Function,-,furi_hal_flash_get_base,size_t, Function,-,furi_hal_flash_get_cycles_count,size_t, -Function,-,furi_hal_flash_get_free_end_address,const void*, +Function,+,furi_hal_flash_get_free_end_address,const void*, Function,-,furi_hal_flash_get_free_page_count,size_t, Function,-,furi_hal_flash_get_free_page_start_address,size_t, -Function,-,furi_hal_flash_get_free_start_address,const void*, +Function,+,furi_hal_flash_get_free_start_address,const void*, Function,-,furi_hal_flash_get_page_number,int16_t,size_t -Function,-,furi_hal_flash_get_page_size,size_t, +Function,+,furi_hal_flash_get_page_size,size_t, Function,-,furi_hal_flash_get_read_block_size,size_t, Function,-,furi_hal_flash_get_write_block_size,size_t, Function,-,furi_hal_flash_init,void, @@ -1640,6 +1615,7 @@ Function,+,furi_hal_rtc_get_log_baud_rate,FuriHalRtcLogBaudRate, Function,+,furi_hal_rtc_get_log_device,FuriHalRtcLogDevice, Function,+,furi_hal_rtc_get_log_level,uint8_t, Function,+,furi_hal_rtc_get_pin_fails,uint32_t, +Function,-,furi_hal_rtc_get_pin_value,uint32_t, Function,+,furi_hal_rtc_get_register,uint32_t,FuriHalRtcRegister Function,+,furi_hal_rtc_get_timestamp,uint32_t, Function,-,furi_hal_rtc_init,void, @@ -1659,6 +1635,7 @@ Function,+,furi_hal_rtc_set_log_baud_rate,void,FuriHalRtcLogBaudRate Function,+,furi_hal_rtc_set_log_device,void,FuriHalRtcLogDevice Function,+,furi_hal_rtc_set_log_level,void,uint8_t Function,+,furi_hal_rtc_set_pin_fails,void,uint32_t +Function,-,furi_hal_rtc_set_pin_value,void,uint32_t Function,+,furi_hal_rtc_set_register,void,"FuriHalRtcRegister, uint32_t" Function,+,furi_hal_rtc_sync_shadow,void, Function,+,furi_hal_sd_get_card_state,FuriStatus, @@ -1848,6 +1825,7 @@ Function,+,furi_semaphore_acquire,FuriStatus,"FuriSemaphore*, uint32_t" Function,+,furi_semaphore_alloc,FuriSemaphore*,"uint32_t, uint32_t" Function,+,furi_semaphore_free,void,FuriSemaphore* Function,+,furi_semaphore_get_count,uint32_t,FuriSemaphore* +Function,+,furi_semaphore_get_space,uint32_t,FuriSemaphore* Function,+,furi_semaphore_release,FuriStatus,FuriSemaphore* Function,+,furi_stream_buffer_alloc,FuriStreamBuffer*,"size_t, size_t" Function,+,furi_stream_buffer_bytes_available,size_t,FuriStreamBuffer* @@ -1876,6 +1854,8 @@ Function,+,furi_string_cmpi_str,int,"const FuriString*, const char[]" Function,+,furi_string_empty,_Bool,const FuriString* Function,+,furi_string_end_with,_Bool,"const FuriString*, const FuriString*" Function,+,furi_string_end_with_str,_Bool,"const FuriString*, const char[]" +Function,+,furi_string_end_withi,_Bool,"const FuriString*, const FuriString*" +Function,+,furi_string_end_withi_str,_Bool,"const FuriString*, const char[]" Function,+,furi_string_equal,_Bool,"const FuriString*, const FuriString*" Function,+,furi_string_equal_str,_Bool,"const FuriString*, const char[]" Function,+,furi_string_free,void,FuriString* @@ -1933,6 +1913,7 @@ Function,+,furi_thread_get_id,FuriThreadId,FuriThread* Function,+,furi_thread_get_name,const char*,FuriThreadId Function,+,furi_thread_get_priority,FuriThreadPriority,FuriThread* Function,+,furi_thread_get_return_code,int32_t,FuriThread* +Function,+,furi_thread_get_signal_callback,FuriThreadSignalCallback,const FuriThread* Function,+,furi_thread_get_stack_space,uint32_t,FuriThreadId Function,+,furi_thread_get_state,FuriThreadState,FuriThread* Function,+,furi_thread_get_stdout_callback,FuriThreadStdoutWriteCallback, @@ -2048,8 +2029,8 @@ Function,+,ibutton_protocols_render_data,void,"iButtonProtocols*, const iButtonK Function,+,ibutton_protocols_render_error,void,"iButtonProtocols*, const iButtonKey*, FuriString*" Function,+,ibutton_protocols_render_uid,void,"iButtonProtocols*, const iButtonKey*, FuriString*" Function,+,ibutton_protocols_save,_Bool,"iButtonProtocols*, const iButtonKey*, const char*" -Function,+,ibutton_protocols_write_id,_Bool,"iButtonProtocols*, iButtonKey*" Function,+,ibutton_protocols_write_copy,_Bool,"iButtonProtocols*, iButtonKey*" +Function,+,ibutton_protocols_write_id,_Bool,"iButtonProtocols*, iButtonKey*" Function,+,ibutton_worker_alloc,iButtonWorker*,iButtonProtocols* Function,+,ibutton_worker_emulate_set_callback,void,"iButtonWorker*, iButtonWorkerEmulateCallback, void*" Function,+,ibutton_worker_emulate_start,void,"iButtonWorker*, iButtonKey*" @@ -2059,8 +2040,8 @@ Function,+,ibutton_worker_read_start,void,"iButtonWorker*, iButtonKey*" Function,+,ibutton_worker_start_thread,void,iButtonWorker* Function,+,ibutton_worker_stop,void,iButtonWorker* Function,+,ibutton_worker_stop_thread,void,iButtonWorker* -Function,+,ibutton_worker_write_id_start,void,"iButtonWorker*, iButtonKey*" Function,+,ibutton_worker_write_copy_start,void,"iButtonWorker*, iButtonKey*" +Function,+,ibutton_worker_write_id_start,void,"iButtonWorker*, iButtonKey*" Function,+,ibutton_worker_write_set_callback,void,"iButtonWorker*, iButtonWorkerWriteCallback, void*" Function,+,icon_animation_alloc,IconAnimation*,const Icon* Function,+,icon_animation_free,void,IconAnimation* @@ -2913,8 +2894,12 @@ Function,+,notification_internal_message,void,"NotificationApp*, const Notificat Function,+,notification_internal_message_block,void,"NotificationApp*, const NotificationSequence*" Function,+,notification_message,void,"NotificationApp*, const NotificationSequence*" Function,+,notification_message_block,void,"NotificationApp*, const NotificationSequence*" -Function,+,notification_message_save_settings,void,NotificationApp* Function,-,nrand48,long,unsigned short[3] +Function,+,number_input_alloc,NumberInput*, +Function,+,number_input_free,void,NumberInput* +Function,+,number_input_get_view,View*,NumberInput* +Function,+,number_input_set_header_text,void,"NumberInput*, const char*" +Function,+,number_input_set_result_callback,void,"NumberInput*, NumberInputCallback, void*, int32_t, int32_t, int32_t" Function,-,on_exit,int,"void (*)(int, void*), void*" Function,+,onewire_host_alloc,OneWireHost*,const GpioPin* Function,+,onewire_host_free,void,OneWireHost* @@ -3011,12 +2996,9 @@ Function,-,pow10f,float,float Function,+,power_enable_low_battery_level_notification,void,"Power*, _Bool" Function,+,power_get_info,void,"Power*, PowerInfo*" Function,+,power_get_pubsub,FuriPubSub*,Power* -Function,+,power_get_settings_events_pubsub,FuriPubSub*,Power* Function,+,power_is_battery_healthy,_Bool,Power* Function,+,power_off,void,Power* -Function,+,power_reboot,void,PowerBootMode -Function,+,power_set_battery_icon_enabled,void,"Power*, _Bool" -Function,-,power_trigger_ui_update,void,Power* +Function,+,power_reboot,void,"Power*, PowerBootMode" Function,+,powf,float,"float, float" Function,-,powl,long double,"long double, long double" Function,+,pretty_format_bytes_hex_canonical,void,"FuriString*, size_t, const char*, const uint8_t*, size_t" @@ -3319,7 +3301,7 @@ Function,+,storage_file_write,size_t,"File*, const void*, size_t" Function,+,storage_get_next_filename,void,"Storage*, const char*, const char*, const char*, FuriString*, uint8_t" Function,+,storage_get_pubsub,FuriPubSub*,Storage* Function,+,storage_int_backup,FS_Error,"Storage*, const char*" -Function,+,storage_int_restore,FS_Error,"Storage*, const char*, Storage_name_converter" +Function,+,storage_int_restore,FS_Error,"Storage*, const char*, StorageNameConverter" Function,+,storage_sd_format,FS_Error,Storage* Function,+,storage_sd_info,FS_Error,"Storage*, SDInfo*" Function,+,storage_sd_mount,FS_Error,Storage* @@ -3646,7 +3628,7 @@ Function,+,tar_archive_set_file_callback,void,"TarArchive*, tar_unpack_file_cb, Function,+,tar_archive_set_read_callback,void,"TarArchive*, tar_unpack_read_cb, void*" Function,+,tar_archive_store_data,_Bool,"TarArchive*, const char*, const uint8_t*, const int32_t" Function,+,tar_archive_unpack_file,_Bool,"TarArchive*, const char*, const char*" -Function,+,tar_archive_unpack_to,_Bool,"TarArchive*, const char*, Storage_name_converter" +Function,+,tar_archive_unpack_to,_Bool,"TarArchive*, const char*, TarArchiveNameConverter" Function,-,tempnam,char*,"const char*, const char*" Function,+,text_box_alloc,TextBox*, Function,+,text_box_free,void,TextBox* @@ -3767,11 +3749,11 @@ Function,+,view_holder_alloc,ViewHolder*, Function,+,view_holder_attach_to_gui,void,"ViewHolder*, Gui*" Function,+,view_holder_free,void,ViewHolder* Function,+,view_holder_get_free_context,void*,ViewHolder* +Function,+,view_holder_send_to_back,void,ViewHolder* +Function,+,view_holder_send_to_front,void,ViewHolder* Function,+,view_holder_set_back_callback,void,"ViewHolder*, BackCallback, void*" Function,+,view_holder_set_free_callback,void,"ViewHolder*, FreeCallback, void*" Function,+,view_holder_set_view,void,"ViewHolder*, View*" -Function,+,view_holder_start,void,ViewHolder* -Function,+,view_holder_stop,void,ViewHolder* Function,+,view_holder_update,void,"View*, void*" Function,+,view_port_alloc,ViewPort*, Function,+,view_port_ascii_callback_set,void,"ViewPort*, ViewPortAsciiCallback, void*" @@ -3849,8 +3831,6 @@ Variable,+,A_Settings_14,const Icon, Variable,+,A_Sub1ghz_14,const Icon, Variable,+,A_U2F_14,const Icon, Variable,+,A_iButton_14,const Icon, -Variable,+,DOLPHIN_LEVELS,const uint32_t[], -Variable,+,DOLPHIN_LEVEL_COUNT,const size_t, Variable,+,FLIPPER_APPS,const FlipperInternalApplication[], Variable,+,FLIPPER_APPS_COUNT,const size_t, Variable,-,FLIPPER_ARCHIVE,const FlipperInternalApplication, @@ -3946,8 +3926,12 @@ Variable,+,I_KeyBackspaceSelected_17x11,const Icon, Variable,+,I_KeyBackspace_17x11,const Icon, Variable,+,I_KeyKeyboardSelected_10x11,const Icon, Variable,+,I_KeyKeyboard_10x11,const Icon, +Variable,+,I_KeySaveBlockedSelected_22x11,const Icon, +Variable,+,I_KeySaveBlocked_22x11,const Icon, Variable,+,I_KeySaveSelected_22x11,const Icon, Variable,+,I_KeySave_22x11,const Icon, +Variable,+,I_KeySignSelected_21x11,const Icon, +Variable,+,I_KeySign_21x11,const Icon, Variable,+,I_Keychain_39x36,const Icon, Variable,+,I_Left_mouse_icon_9x9,const Icon, Variable,+,I_LoadingHourglass_24x24,const Icon, diff --git a/targets/f7/ble_glue/extra_beacon.c b/targets/f7/ble_glue/extra_beacon.c index 0fd452a5a..f9b9b13ef 100644 --- a/targets/f7/ble_glue/extra_beacon.c +++ b/targets/f7/ble_glue/extra_beacon.c @@ -8,9 +8,9 @@ #define GAP_MS_TO_SCAN_INTERVAL(x) ((uint16_t)((x) / 0.625)) -// Also used as an indicator of whether the beacon had ever been configured -// AN5289: 4.7, we need at least 25ms + advertisement, which is 30 ms -#define GAP_MIN_ADV_INTERVAL_MS (30u) +// AN5289: 4.7, in order to use flash controller interval must be at least 25ms + advertisement, which is 30 ms +// Since we don't use flash controller anymore interval can be lowered to 20ms +#define GAP_MIN_ADV_INTERVAL_MS (20U) typedef struct { GapExtraBeaconConfig last_config; diff --git a/targets/f7/ble_glue/hw_ipcc.c b/targets/f7/ble_glue/hw_ipcc.c index 4daaa7e49..43785a1b4 100644 --- a/targets/f7/ble_glue/hw_ipcc.c +++ b/targets/f7/ble_glue/hw_ipcc.c @@ -15,6 +15,8 @@ (LL_C2_IPCC_IsActiveFlag_CHx(IPCC, channel) && \ LL_C1_IPCC_IsEnabledReceiveChannel(IPCC, channel)) +#define IPCC_SEND_CMD_TIMEOUT_US (33UL * 1000UL * 1000UL) + static void (*FreeBufCb)(void); static void HW_IPCC_BLE_EvtHandler(void); @@ -113,7 +115,7 @@ void HW_IPCC_SYS_Init(void) { void HW_IPCC_SYS_SendCmd(void) { LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_SYSTEM_CMD_RSP_CHANNEL); - FuriHalCortexTimer timer = furi_hal_cortex_timer_get(33000000); + FuriHalCortexTimer timer = furi_hal_cortex_timer_get(IPCC_SEND_CMD_TIMEOUT_US); while(LL_C1_IPCC_IsActiveFlag_CHx(IPCC, HW_IPCC_SYSTEM_CMD_RSP_CHANNEL)) { furi_check(!furi_hal_cortex_timer_is_expired(timer), "HW_IPCC_SYS_SendCmd timeout"); diff --git a/targets/f7/ble_glue/profiles/serial_profile.c b/targets/f7/ble_glue/profiles/serial_profile.c index 118a76e8c..1d414889f 100644 --- a/targets/f7/ble_glue/profiles/serial_profile.c +++ b/targets/f7/ble_glue/profiles/serial_profile.c @@ -40,14 +40,20 @@ static void ble_profile_serial_stop(FuriHalBleProfileBase* profile) { ble_svc_serial_stop(serial_profile->serial_svc); } +// AN5289: 4.7, in order to use flash controller interval must be at least 25ms + advertisement, which is 30 ms +// Since we don't use flash controller anymore interval can be lowered to 7.5ms +#define CONNECTION_INTERVAL_MIN (0x06) +// Up to 45 ms +#define CONNECTION_INTERVAL_MAX (0x24) + static GapConfig serial_template_config = { .adv_service_uuid = 0x3080, .appearance_char = 0x8600, .bonding_mode = true, .pairing_method = GapPairingPinCodeShow, .conn_param = { - .conn_int_min = 0x18, // AN5289: 4.7, we need at least 25ms + advertisement, which is 30 ms - .conn_int_max = 0x24, // 45 ms + .conn_int_min = CONNECTION_INTERVAL_MIN, + .conn_int_max = CONNECTION_INTERVAL_MAX, .slave_latency = 0, .supervisor_timeout = 0, }}; diff --git a/targets/f7/furi_hal/furi_hal_bt.c b/targets/f7/furi_hal/furi_hal_bt.c index af48bcb9c..e7882576d 100644 --- a/targets/f7/furi_hal/furi_hal_bt.c +++ b/targets/f7/furi_hal/furi_hal_bt.c @@ -87,10 +87,9 @@ static bool furi_hal_bt_radio_stack_is_supported(const BleGlueC2Info* info) { } bool furi_hal_bt_start_radio_stack(void) { - bool res = false; - furi_check(furi_hal_bt.core2_mtx); + furi_hal_bt_lock_core2(); - furi_mutex_acquire(furi_hal_bt.core2_mtx, FuriWaitForever); + bool res = false; // Explicitly tell that we are in charge of CLK48 domain furi_check(LL_HSEM_1StepLock(HSEM, CFG_HW_CLK48_CONFIG_SEMID) == 0); @@ -123,7 +122,8 @@ bool furi_hal_bt_start_radio_stack(void) { } res = true; } while(false); - furi_mutex_release(furi_hal_bt.core2_mtx); + + furi_hal_bt_unlock_core2(); gap_extra_beacon_init(); return res; @@ -198,6 +198,8 @@ FuriHalBleProfileBase* furi_hal_bt_start_app( } void furi_hal_bt_reinit(void) { + furi_hal_bt_lock_core2(); + furi_hal_power_insomnia_enter(); FURI_LOG_I(TAG, "Disconnect and stop advertising"); furi_hal_bt_stop_advertising(); @@ -229,6 +231,7 @@ void furi_hal_bt_reinit(void) { furi_hal_bus_disable(FuriHalBusCRC); furi_hal_bt_init(); + furi_hal_bt_unlock_core2(); furi_hal_bt_start_radio_stack(); furi_hal_power_insomnia_exit(); } diff --git a/targets/f7/furi_hal/furi_hal_crypto.c b/targets/f7/furi_hal/furi_hal_crypto.c index 1879eb2ca..4deda293a 100644 --- a/targets/f7/furi_hal/furi_hal_crypto.c +++ b/targets/f7/furi_hal/furi_hal_crypto.c @@ -262,36 +262,54 @@ bool furi_hal_crypto_enclave_load_key(uint8_t slot, const uint8_t* iv) { furi_hal_bus_enable(FuriHalBusAES1); - if(!furi_hal_bt_is_alive()) { - return false; - } + bool success = false; - furi_hal_crypto_mode_init_done = false; - crypto_key_init(NULL, (uint32_t*)iv); + furi_hal_bt_lock_core2(); - if(SHCI_C2_FUS_LoadUsrKey(slot) == SHCI_Success) { - return true; - } else { - CLEAR_BIT(AES1->CR, AES_CR_EN); - furi_check(furi_mutex_release(furi_hal_crypto_mutex) == FuriStatusOk); - return false; - } + do { + if(!furi_hal_bt_is_alive()) { + break; + } + + furi_hal_crypto_mode_init_done = false; + crypto_key_init(NULL, (uint32_t*)iv); + + if(SHCI_C2_FUS_LoadUsrKey(slot) == SHCI_Success) { + success = true; + } else { + CLEAR_BIT(AES1->CR, AES_CR_EN); + furi_check(furi_mutex_release(furi_hal_crypto_mutex) == FuriStatusOk); + } + + } while(false); + + furi_hal_bt_unlock_core2(); + return success; } bool furi_hal_crypto_enclave_unload_key(uint8_t slot) { - if(!furi_hal_bt_is_alive()) { - return false; - } + furi_hal_bt_lock_core2(); - CLEAR_BIT(AES1->CR, AES_CR_EN); + bool success = false; - SHCI_CmdStatus_t shci_state = SHCI_C2_FUS_UnloadUsrKey(slot); + do { + if(!furi_hal_bt_is_alive()) { + break; + } - furi_hal_bus_disable(FuriHalBusAES1); + CLEAR_BIT(AES1->CR, AES_CR_EN); - furi_check(furi_mutex_release(furi_hal_crypto_mutex) == FuriStatusOk); + SHCI_CmdStatus_t shci_state = SHCI_C2_FUS_UnloadUsrKey(slot); - return shci_state == SHCI_Success; + furi_hal_bus_disable(FuriHalBusAES1); + + furi_check(furi_mutex_release(furi_hal_crypto_mutex) == FuriStatusOk); + + success = (shci_state == SHCI_Success); + } while(false); + + furi_hal_bt_unlock_core2(); + return success; } bool furi_hal_crypto_load_key(const uint8_t* key, const uint8_t* iv) { diff --git a/targets/f7/furi_hal/furi_hal_infrared.c b/targets/f7/furi_hal/furi_hal_infrared.c index 029d103cb..a1169391d 100644 --- a/targets/f7/furi_hal/furi_hal_infrared.c +++ b/targets/f7/furi_hal/furi_hal_infrared.c @@ -54,6 +54,7 @@ typedef struct { typedef struct { float cycle_duration; + float cycle_remainder; FuriHalInfraredTxGetDataISRCallback data_callback; FuriHalInfraredTxSignalSentISRCallback signal_sent_callback; void* data_context; @@ -512,7 +513,11 @@ static void furi_hal_infrared_tx_fill_buffer(uint8_t buf_num, uint8_t polarity_s status = infrared_tim_tx.data_callback(infrared_tim_tx.data_context, &duration, &level); - uint32_t num_of_impulses = roundf(duration / infrared_tim_tx.cycle_duration); + const float num_of_impulses_f = + duration / infrared_tim_tx.cycle_duration + infrared_tim_tx.cycle_remainder; + const uint32_t num_of_impulses = roundf(num_of_impulses_f); + // Save the remainder (in carrier periods) for later use + infrared_tim_tx.cycle_remainder = num_of_impulses_f - num_of_impulses; if(num_of_impulses == 0) { if((*size == 0) && (status == FuriHalInfraredTxGetDataStateDone)) { @@ -521,7 +526,7 @@ static void furi_hal_infrared_tx_fill_buffer(uint8_t buf_num, uint8_t polarity_s */ status = FuriHalInfraredTxGetDataStateOk; } - } else if((num_of_impulses - 1) > 0xFFFF) { + } else if((num_of_impulses - 1) > UINT16_MAX) { infrared_tim_tx.tx_timing_rest_duration = num_of_impulses - 1; infrared_tim_tx.tx_timing_rest_status = status; infrared_tim_tx.tx_timing_rest_level = level; @@ -632,6 +637,7 @@ void furi_hal_infrared_async_tx_start(uint32_t freq, float duty_cycle) { infrared_tim_tx.stop_semaphore = furi_semaphore_alloc(1, 0); infrared_tim_tx.cycle_duration = 1000000.0 / freq; infrared_tim_tx.tx_timing_rest_duration = 0; + infrared_tim_tx.cycle_remainder = 0; furi_hal_infrared_tx_fill_buffer(0, INFRARED_POLARITY_SHIFT); @@ -655,7 +661,7 @@ void furi_hal_infrared_async_tx_start(uint32_t freq, float duty_cycle) { const GpioPin* tx_gpio = infrared_tx_pins[infrared_tx_output]; LL_GPIO_ResetOutputPin(tx_gpio->port, tx_gpio->pin); /* when disable it prevents false pulse */ furi_hal_gpio_init_ex( - tx_gpio, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedHigh, GpioAltFn1TIM1); + tx_gpio, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedHigh, GpioAltFn1TIM1); FURI_CRITICAL_ENTER(); LL_TIM_GenerateEvent_UPDATE(INFRARED_DMA_TIMER); /* TIMx_RCR -> Repetition counter */ diff --git a/targets/f7/furi_hal/furi_hal_region.c b/targets/f7/furi_hal/furi_hal_region.c index 3808a8bc6..5bf4048fa 100644 --- a/targets/f7/furi_hal/furi_hal_region.c +++ b/targets/f7/furi_hal/furi_hal_region.c @@ -72,55 +72,68 @@ const FuriHalRegion furi_hal_region_jp = { .duty_cycle = 50, }}}; -static const FuriHalRegion* furi_hal_region = NULL; +static const FuriHalRegion* const furi_hal_static_regions[] = { + [FuriHalVersionRegionUnknown] = &furi_hal_region_zero, + [FuriHalVersionRegionEuRu] = &furi_hal_region_eu_ru, + [FuriHalVersionRegionUsCaAu] = &furi_hal_region_us_ca_au, + [FuriHalVersionRegionJp] = &furi_hal_region_jp, +}; + +static FuriHalRegion* furi_hal_dynamic_region; +static FuriMutex* furi_hal_dynamic_region_mutex; void furi_hal_region_init(void) { - FuriHalVersionRegion region = furi_hal_version_get_hw_region(); - - if(region == FuriHalVersionRegionUnknown) { - furi_hal_region = &furi_hal_region_zero; - } else if(region == FuriHalVersionRegionEuRu) { - furi_hal_region = &furi_hal_region_eu_ru; - } else if(region == FuriHalVersionRegionUsCaAu) { - furi_hal_region = &furi_hal_region_us_ca_au; - } else if(region == FuriHalVersionRegionJp) { - furi_hal_region = &furi_hal_region_jp; - } + furi_assert(furi_hal_dynamic_region_mutex == NULL); + furi_hal_dynamic_region_mutex = furi_mutex_alloc(FuriMutexTypeNormal); } const FuriHalRegion* furi_hal_region_get(void) { - return furi_hal_region; + const FuriHalVersionRegion region = furi_hal_version_get_hw_region(); + const FuriHalRegion* ret; + + furi_check(furi_mutex_acquire(furi_hal_dynamic_region_mutex, FuriWaitForever) == FuriStatusOk); + + if(region < FuriHalVersionRegionWorld && furi_hal_dynamic_region == NULL) { + ret = furi_hal_static_regions[region]; + } else { + ret = furi_hal_dynamic_region; + } + + furi_check(furi_mutex_release(furi_hal_dynamic_region_mutex) == FuriStatusOk); + + return ret; } void furi_hal_region_set(FuriHalRegion* region) { furi_check(region); - furi_hal_region = region; + furi_check(furi_mutex_acquire(furi_hal_dynamic_region_mutex, FuriWaitForever) == FuriStatusOk); + + if(furi_hal_dynamic_region) { + free(furi_hal_dynamic_region); + } + + furi_hal_dynamic_region = region; + + furi_check(furi_mutex_release(furi_hal_dynamic_region_mutex) == FuriStatusOk); } bool furi_hal_region_is_provisioned(void) { - return furi_hal_region != NULL; + return furi_hal_region_get() != NULL; } const char* furi_hal_region_get_name(void) { - if(furi_hal_region) { - return furi_hal_region->country_code; + const FuriHalRegion* region = furi_hal_region_get(); + + if(region) { + return region->country_code; } else { return "--"; } } bool _furi_hal_region_is_frequency_allowed(uint32_t frequency) { - if(!furi_hal_region) { - return false; - } - - const FuriHalRegionBand* band = furi_hal_region_get_band(frequency); - if(!band) { - return false; - } - - return true; + return furi_hal_region_get_band(frequency) != NULL; } // Check furi_hal_subghz settings for region bypass, if not it uses function above @@ -129,14 +142,15 @@ bool furi_hal_region_is_frequency_allowed(uint32_t frequency) { } const FuriHalRegionBand* furi_hal_region_get_band(uint32_t frequency) { - if(!furi_hal_region) { + const FuriHalRegion* region = furi_hal_region_get(); + + if(!region) { return NULL; } - for(size_t i = 0; i < furi_hal_region->bands_count; i++) { - if(furi_hal_region->bands[i].start <= frequency && - furi_hal_region->bands[i].end >= frequency) { - return &furi_hal_region->bands[i]; + for(size_t i = 0; i < region->bands_count; i++) { + if(region->bands[i].start <= frequency && region->bands[i].end >= frequency) { + return ®ion->bands[i]; } } diff --git a/targets/f7/furi_hal/furi_hal_rtc.c b/targets/f7/furi_hal/furi_hal_rtc.c index f5f7bdf2d..d5cda7476 100644 --- a/targets/f7/furi_hal/furi_hal_rtc.c +++ b/targets/f7/furi_hal/furi_hal_rtc.c @@ -411,6 +411,14 @@ uint32_t furi_hal_rtc_get_pin_fails(void) { return furi_hal_rtc_get_register(FuriHalRtcRegisterPinFails); } +void furi_hal_rtc_set_pin_value(uint32_t value) { + furi_hal_rtc_set_register(FuriHalRtcRegisterPinValue, value); +} + +uint32_t furi_hal_rtc_get_pin_value(void) { + return furi_hal_rtc_get_register(FuriHalRtcRegisterPinValue); +} + uint32_t furi_hal_rtc_get_timestamp(void) { DateTime datetime = {0}; furi_hal_rtc_get_datetime(&datetime); diff --git a/targets/f7/furi_hal/furi_hal_rtc.h b/targets/f7/furi_hal/furi_hal_rtc.h index f23e0953f..96c9f80de 100644 --- a/targets/f7/furi_hal/furi_hal_rtc.h +++ b/targets/f7/furi_hal/furi_hal_rtc.h @@ -46,9 +46,10 @@ typedef enum { FuriHalRtcRegisterVersion, /**< Pointer to Version */ FuriHalRtcRegisterLfsFingerprint, /**< LFS geometry fingerprint */ FuriHalRtcRegisterFaultData, /**< Pointer to last fault message */ - FuriHalRtcRegisterPinFails, /**< Failed pins count */ + FuriHalRtcRegisterPinFails, /**< Failed PINs count */ /* Index of FS directory entry corresponding to FW update to be applied */ FuriHalRtcRegisterUpdateFolderFSIndex, + FuriHalRtcRegisterPinValue, /**< Encoded value of the currently set PIN */ FuriHalRtcRegisterMAX, /**< Service value, do not use */ } FuriHalRtcRegister; @@ -257,18 +258,29 @@ void furi_hal_rtc_set_fault_data(uint32_t value); */ uint32_t furi_hal_rtc_get_fault_data(void); -/** Set Pin Fails count +/** Set PIN Fails count * - * @param[in] value The Pin Fails count + * @param[in] value The PIN Fails count */ void furi_hal_rtc_set_pin_fails(uint32_t value); -/** Get Pin Fails count +/** Get PIN Fails count * - * @return Pin Fails Count + * @return PIN Fails Count */ uint32_t furi_hal_rtc_get_pin_fails(void); +/** Set encoded PIN value + * + * @param[in] value new PIN code value to be set + */ +void furi_hal_rtc_set_pin_value(uint32_t value); + +/** Get the current PIN encoded value + * + */ +uint32_t furi_hal_rtc_get_pin_value(void); + /** Get UNIX Timestamp * * @return Unix Timestamp in seconds from UNIX epoch start diff --git a/targets/f7/target.json b/targets/f7/target.json index c7bffe45f..c5a65704a 100644 --- a/targets/f7/target.json +++ b/targets/f7/target.json @@ -25,7 +25,6 @@ "stm32wb", "hwdrivers", "fatfs", - "littlefs", "subghz", "toolbox", "nfc", @@ -36,7 +35,6 @@ "microtar", "usb_stm32", "infrared", - "appframe", "assets", "one_wire", "ibutton", diff --git a/targets/furi_hal_include/furi_hal_region.h b/targets/furi_hal_include/furi_hal_region.h index eed5bef92..79a823ba4 100644 --- a/targets/furi_hal_include/furi_hal_region.h +++ b/targets/furi_hal_include/furi_hal_region.h @@ -2,7 +2,6 @@ #include #include -#include #ifdef __cplusplus extern "C" {