Przeglądaj źródła

Merge branch 'dev' into main

MX 2 lat temu
rodzic
commit
6647fb0222
72 zmienionych plików z 377 dodań i 2312 usunięć
  1. 2 2
      ReadMe.md
  2. BIN
      apps/Bluetooth/bt_trigger.fap
  3. BIN
      apps/GPIO/airmon.fap
  4. BIN
      apps/GPIO/gpio_7segment_output.fap
  5. BIN
      apps/GPIO/gpio_timelapse.fap
  6. BIN
      apps/GPIO/memsic_2125.fap
  7. BIN
      apps/GPIO/rcwl_0516.fap
  8. BIN
      apps/GPIO/servotester.fap
  9. BIN
      apps/GPIO/servotester2.fap
  10. BIN
      apps/GPIO/wii_ec_anal.fap
  11. BIN
      apps/Games/reaction.fap
  12. BIN
      apps/Games/reversi.fap
  13. BIN
      apps/Games/rubiks_cube_scrambler.fap
  14. BIN
      apps/Games/slotmachine.fap
  15. BIN
      apps/Games/t_rex_runner.fap
  16. BIN
      apps/Infrared/ir_remote.fap
  17. BIN
      apps/Infrared/sony_intervalometer.fap
  18. BIN
      apps/Tools/passgen.fap
  19. BIN
      apps/Tools/qrcode.fap
  20. 0 2
      apps_source_code/airmon/airmon.c
  21. 1 1
      apps_source_code/airmon/application.fam
  22. 1 1
      apps_source_code/bluetooth-trigger/application.fam
  23. 5 2
      apps_source_code/bluetooth-trigger/bt_trigger.c
  24. 4 4
      apps_source_code/bluetooth-trigger/bt_trigger.h
  25. 3 0
      apps_source_code/flipper_passgen/application.fam
  26. 75 16
      apps_source_code/flipper_passgen/passgen.c
  27. 1 1
      apps_source_code/flipperzero-slots/application.fam
  28. 37 33
      apps_source_code/flipperzero-slots/slotmachine.c
  29. 1 1
      apps_source_code/fz-reaction-game/application.fam
  30. 1 0
      apps_source_code/fz-reaction-game/reaction.c
  31. 1 1
      apps_source_code/gpio_7segment/application.fam
  32. 6 1
      apps_source_code/gpio_7segment/gpio_7segment_app.c
  33. 1 1
      apps_source_code/reversi/application.fam
  34. 2 1
      apps_source_code/reversi/game_reversi.c
  35. 1 1
      apps_source_code/rubiks_cube_scrambler/application.fam
  36. 1 0
      apps_source_code/rubiks_cube_scrambler/rubiks_cube_scrambler.c
  37. 1 1
      apps_source_code/servotester/application.fam
  38. 3 0
      apps_source_code/servotester/servotester.c
  39. 1 1
      apps_source_code/sony-intervalometer/application.fam
  40. 2 0
      apps_source_code/sony-intervalometer/intervalometer.c
  41. 1 1
      apps_source_code/t-rex-runner/application.fam
  42. 16 8
      apps_source_code/t-rex-runner/trexrunner.c
  43. 1 1
      apps_source_code/timelapse/application.fam
  44. 3 0
      apps_source_code/timelapse/zeitraffer.c
  45. 1 1
      main_apps_sources/hex_viewer/application.fam
  46. 51 46
      main_apps_sources/hex_viewer/hex_viewer.c
  47. 1 1
      main_apps_sources/ir_scope/application.fam
  48. 23 22
      main_apps_sources/ir_scope/ir_scope.c
  49. 1 1
      main_apps_sources/text_viewer/application.fam
  50. 51 49
      main_apps_sources/text_viewer/text_viewer.c
  51. 1 0
      non_catalog_apps/ServoTesterApp/app.c
  52. 67 66
      non_catalog_apps/flipperzero-qrcode/qrcode_app.c
  53. 1 0
      non_catalog_apps/ir_remote/infrared_remote_app.c
  54. 1 0
      non_catalog_apps/memsic_2125/memsic_2125_app.c
  55. 4 0
      non_catalog_apps/rcwl_0516/rcwl_0516.c
  56. 0 15
      non_catalog_apps/solitaire/application.fam
  57. BIN
      non_catalog_apps/solitaire/assets/card_graphics.png
  58. BIN
      non_catalog_apps/solitaire/assets/solitaire_main.png
  59. 0 353
      non_catalog_apps/solitaire/common/card.c
  60. 0 192
      non_catalog_apps/solitaire/common/card.h
  61. 0 53
      non_catalog_apps/solitaire/common/dml.c
  62. 0 116
      non_catalog_apps/solitaire/common/dml.h
  63. 0 103
      non_catalog_apps/solitaire/common/menu.c
  64. 0 77
      non_catalog_apps/solitaire/common/menu.h
  65. 0 69
      non_catalog_apps/solitaire/common/queue.c
  66. 0 70
      non_catalog_apps/solitaire/common/queue.h
  67. 0 257
      non_catalog_apps/solitaire/common/ui.c
  68. 0 105
      non_catalog_apps/solitaire/common/ui.h
  69. 0 57
      non_catalog_apps/solitaire/defines.h
  70. 0 575
      non_catalog_apps/solitaire/solitaire.c
  71. BIN
      non_catalog_apps/solitaire/solitaire_10px.png
  72. 4 4
      non_catalog_apps/wii_ec_anal/wii_anal.c

+ 2 - 2
ReadMe.md

@@ -20,7 +20,7 @@ Sources of "integrated/bundled" apps are added now in this repo too, to allow pu
 
 The Flipper and its community wouldn't be as rich as it is without your contributions and support. Thank you for all you have done.
 
-### Apps checked & updated at `24 Jul 01:07 GMT +3`
+### Apps checked & updated at `25 Jul 04:13 GMT +3`
 
 ## Games
 - [Pong (By nmrr)](https://github.com/nmrr/flipperzero-pong) - Modified by [SimplyMinimal](https://github.com/SimplyMinimal/FlipperZero-Pong)
@@ -108,7 +108,7 @@ The Flipper and its community wouldn't be as rich as it is without your contribu
 - [Counter (By Krulknul)](https://github.com/Krulknul/dolphin-counter)
 - [USB HID Autofire (By pbek)](https://github.com/pbek/usb_hid_autofire)
 - [IR Remote (By Hong5489)](https://github.com/Hong5489/ir_remote) - improvements [(By friebel)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/535) - Hold Option, RAW support [(By d4ve10)](https://github.com/d4ve10/ir_remote/tree/infrared_hold_option)
-- [Password Generator (By anakod)](https://github.com/anakod/flipper_passgen)
+- [Password Generator (By anakod)](https://github.com/anakod/flipper_passgen) - Proper random by [henrygab](https://github.com/anakod/flipper_passgen/pull/6)
 - [Count Down Timer (By 0w0mewo)](https://github.com/0w0mewo/fpz_cntdown_timer)
 - [QR Code (By bmatcuk)](https://github.com/bmatcuk/flipperzero-qrcode)
 - [Flipp Pomodoro Timer (By Th3Un1q3)](https://github.com/Th3Un1q3/flipp_pomodoro)

BIN
apps/Bluetooth/bt_trigger.fap


BIN
apps/GPIO/airmon.fap


BIN
apps/GPIO/gpio_7segment_output.fap


BIN
apps/GPIO/gpio_timelapse.fap


BIN
apps/GPIO/memsic_2125.fap


BIN
apps/GPIO/rcwl_0516.fap


BIN
apps/GPIO/servotester.fap


BIN
apps/GPIO/servotester2.fap


BIN
apps/GPIO/wii_ec_anal.fap


BIN
apps/Games/reaction.fap


BIN
apps/Games/reversi.fap


BIN
apps/Games/rubiks_cube_scrambler.fap


BIN
apps/Games/slotmachine.fap


BIN
apps/Games/t_rex_runner.fap


BIN
apps/Infrared/ir_remote.fap


BIN
apps/Infrared/sony_intervalometer.fap


BIN
apps/Tools/passgen.fap


BIN
apps/Tools/qrcode.fap


+ 0 - 2
apps_source_code/airmon/airmon.c

@@ -207,8 +207,6 @@ static void airmon_run(AirmonContext* ctx) {
                     }
                 }
             }
-        } else {
-            FURI_LOG_D(TAG, "FuriMessageQueue: event timeout");
         }
 
         power_get_info(ctx->power, &ctx->power_info);

+ 1 - 1
apps_source_code/airmon/application.fam

@@ -10,6 +10,6 @@ App(
     fap_icon_assets="icons",
     fap_author="3cky",
     fap_weburl="https://github.com/3cky/flipperzero-airmon",
-    fap_version="1.0",
+    fap_version="1.1",
     fap_description="Plantower PMSx003 sensor reader",
 )

+ 1 - 1
apps_source_code/bluetooth-trigger/application.fam

@@ -11,6 +11,6 @@ App(
     fap_icon_assets="assets",
     fap_author="@Nem0oo",
     fap_weburl="https://github.com/Nem0oo/flipper-zero-bluetooth-trigger",
-    fap_version="1.1",
+    fap_version="1.2",
     fap_description="Control your smartphone camera via your Flipper Zero",
 )

+ 5 - 2
apps_source_code/bluetooth-trigger/bt_trigger.c

@@ -5,10 +5,10 @@ __int32_t bt_trigger_app(void* p) {
     UNUSED(p);
     AppStruct* app = appStructAlloc();
 
-    bt_disconnect(app->bt);
+    //bt_disconnect(app->bt);
 
     // Wait 2nd core to update nvm storage
-    furi_delay_ms(200);
+    //furi_delay_ms(200);
 
     bt_keys_storage_set_storage_path(app->bt, HID_BT_KEYS_STORAGE_PATH);
 
@@ -97,6 +97,7 @@ __int32_t bt_trigger_app(void* p) {
                     break;
                 }
             }
+            view_port_update(app->view_port);
             break;
         case(EventTypeTick):
             if(app->shooting) {
@@ -106,6 +107,7 @@ __int32_t bt_trigger_app(void* p) {
                 notification_message(app->notifications, &sequence_blink_blue_100);
                 app->shots++;
             }
+            view_port_update(app->view_port);
             break;
         default:
             break;
@@ -208,6 +210,7 @@ static void bt_hid_connection_status_changed_callback(BtStatus status, void* con
     furi_assert(context);
     AppStruct* app = context;
     app->connected = (status == BtStatusConnected);
+    view_port_update(app->view_port);
 }
 
 AppStruct* appStructAlloc() {

+ 4 - 4
apps_source_code/bluetooth-trigger/bt_trigger.h

@@ -15,17 +15,17 @@
 #include <dolphin/dolphin.h>
 #include "bt_trigger_icons.h"
 
-#define HID_BT_KEYS_STORAGE_PATH EXT_PATH("apps_data/bt_trigger/hid.keys")
+#define HID_BT_KEYS_STORAGE_PATH EXT_PATH("apps_data/hid_ble/.bt_hid.keys")
 #define TAG "bt_trigger"
 
-//Enum of allowed event types
+// Enum of allowed event types
 typedef enum {
     EventTypeTick,
     EventTypeInput,
 
 } EventType;
 
-//Struct to store an event and its type
+// Struct to store an event and its type
 typedef struct {
     EventType type;
     InputEvent input;
@@ -40,7 +40,7 @@ typedef struct {
     bool running;
     bool shooting;
     int shots;
-    int delay; //in ms
+    int delay; // in ms
 } AppStruct;
 
 static void draw_callback(Canvas* canvas, void* ctx);

+ 3 - 0
apps_source_code/flipper_passgen/application.fam

@@ -9,4 +9,7 @@ App(
     fap_category="Tools",
     fap_icon="icons/passgen_icon.png",
     fap_icon_assets="icons",
+    fap_author="@anakod & @henrygab",
+    fap_version="1.1",
+    fap_description="Simple password generator",
 )

+ 75 - 16
apps_source_code/flipper_passgen/passgen.c

@@ -1,18 +1,19 @@
 #include <furi.h>
+#include <furi_hal_random.h>
 #include <gui/gui.h>
 #include <gui/elements.h>
 #include <input/input.h>
 #include <notification/notification_messages.h>
 #include <stdlib.h>
 #include <passgen_icons.h>
-#include <core/string.h>
 
 #define PASSGEN_MAX_LENGTH 16
+#define PASSGEN_CHARACTERS_LENGTH (26 * 4)
 
 #define PASSGEN_DIGITS "0123456789"
 #define PASSGEN_LETTERS_LOW "abcdefghijklmnopqrstuvwxyz"
 #define PASSGEN_LETTERS_UP "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-#define PASSGEN_SPECIAL "!#$%%^&*.-_"
+#define PASSGEN_SPECIAL "!#$%^&*.-_"
 
 typedef enum PassGen_Alphabet {
     Digits = 1,
@@ -26,6 +27,25 @@ typedef enum PassGen_Alphabet {
     Mixed = DigitsAllLetters | Special
 } PassGen_Alphabet;
 
+const char* const PassGen_AlphabetChars[16] = {
+    "0", // invalid value
+    /*    PASSGEN_SPECIAL    PASSGEN_LETTERS_UP    PASSGEN_LETTERS_LOW */ PASSGEN_DIGITS,
+    /*    PASSGEN_SPECIAL    PASSGEN_LETTERS_UP */ PASSGEN_LETTERS_LOW /* PASSGEN_DIGITS */,
+    /*    PASSGEN_SPECIAL    PASSGEN_LETTERS_UP */ PASSGEN_LETTERS_LOW PASSGEN_DIGITS,
+    /*    PASSGEN_SPECIAL */ PASSGEN_LETTERS_UP /* PASSGEN_LETTERS_LOW    PASSGEN_DIGITS */,
+    /*    PASSGEN_SPECIAL */ PASSGEN_LETTERS_UP /* PASSGEN_LETTERS_LOW */ PASSGEN_DIGITS,
+    /*    PASSGEN_SPECIAL */ PASSGEN_LETTERS_UP PASSGEN_LETTERS_LOW /* PASSGEN_DIGITS */,
+    /*    PASSGEN_SPECIAL */ PASSGEN_LETTERS_UP PASSGEN_LETTERS_LOW PASSGEN_DIGITS,
+    PASSGEN_SPECIAL /* PASSGEN_LETTERS_UP    PASSGEN_LETTERS_LOW    PASSGEN_DIGITS */,
+    PASSGEN_SPECIAL /* PASSGEN_LETTERS_UP    PASSGEN_LETTERS_LOW */ PASSGEN_DIGITS,
+    PASSGEN_SPECIAL /* PASSGEN_LETTERS_UP */ PASSGEN_LETTERS_LOW /* PASSGEN_DIGITS */,
+    PASSGEN_SPECIAL /* PASSGEN_LETTERS_UP */ PASSGEN_LETTERS_LOW PASSGEN_DIGITS,
+    PASSGEN_SPECIAL PASSGEN_LETTERS_UP /* PASSGEN_LETTERS_LOW    PASSGEN_DIGITS */,
+    PASSGEN_SPECIAL PASSGEN_LETTERS_UP /* PASSGEN_LETTERS_LOW */ PASSGEN_DIGITS,
+    PASSGEN_SPECIAL PASSGEN_LETTERS_UP PASSGEN_LETTERS_LOW /* PASSGEN_DIGITS */,
+    PASSGEN_SPECIAL PASSGEN_LETTERS_UP PASSGEN_LETTERS_LOW PASSGEN_DIGITS,
+};
+
 const int AlphabetLevels[] = {Digits, Lowercase, DigitsLower, DigitsAllLetters, Mixed};
 const char* AlphabetLevelNames[] = {"1234", "abcd", "ab12", "Ab12", "Ab1#"};
 const int AlphabetLevelsCount = sizeof(AlphabetLevels) / sizeof(int);
@@ -44,21 +64,24 @@ typedef struct {
     Gui* gui;
     FuriMutex** mutex;
     NotificationApp* notify;
+    const char* alphabet;
     char password[PASSGEN_MAX_LENGTH + 1];
-    // char alphabet[PASSGEN_CHARACTERS_LENGTH + 1];
-    FuriString* alphabet;
-    int length;
+    int length; // must be <= PASSGEN_MAX_LENGTH
     int level;
 } PassGen;
 
 void state_free(PassGen* app) {
+    // NOTE: would have preferred if a "safe" memset() was available...
+    //       but, since cannot prevent optimization from removing
+    //       memset(), fill with random data instead.
+    furi_hal_random_fill_buf((void*)(app->password), PASSGEN_MAX_LENGTH);
+
     gui_remove_view_port(app->gui, app->view_port);
     furi_record_close(RECORD_GUI);
     view_port_free(app->view_port);
     furi_message_queue_free(app->input_queue);
     furi_mutex_free(app->mutex);
     furi_record_close(RECORD_NOTIFICATION);
-    furi_string_free(app->alphabet);
     free(app);
 }
 
@@ -100,17 +123,19 @@ static void render_callback(Canvas* canvas, void* ctx) {
 
 void build_alphabet(PassGen* app) {
     PassGen_Alphabet mode = AlphabetLevels[app->level];
-    if((mode & Digits) != 0) furi_string_cat(app->alphabet, PASSGEN_DIGITS);
-    if((mode & Lowercase) != 0) furi_string_cat(app->alphabet, PASSGEN_LETTERS_LOW);
-    if((mode & Uppercase) != 0) furi_string_cat(app->alphabet, PASSGEN_LETTERS_UP);
-    if((mode & Special) != 0) furi_string_cat(app->alphabet, PASSGEN_SPECIAL);
+    if(mode > 0 && mode < 16) {
+        app->alphabet = PassGen_AlphabetChars[mode];
+    } else {
+        app->alphabet =
+            PassGen_AlphabetChars[0]; // Invalid mode ... password will be all zero digits
+    }
 }
 
 PassGen* state_init() {
     PassGen* app = malloc(sizeof(PassGen));
+    _Static_assert(8 <= PASSGEN_MAX_LENGTH, "app->length must be set <= PASSGEN_MAX_LENGTH");
     app->length = 8;
     app->level = 2;
-    app->alphabet = furi_string_alloc();
     build_alphabet(app);
     app->input_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
     app->view_port = view_port_alloc();
@@ -126,12 +151,46 @@ PassGen* state_init() {
 }
 
 void generate(PassGen* app) {
-    int hi = furi_string_size(app->alphabet);
-    for(int i = 0; i < app->length; i++) {
-        int x = rand() % hi;
-        app->password[i] = furi_string_get_char(app->alphabet, x);
+    memset(app->password, 0, PASSGEN_MAX_LENGTH + 1);
+
+    int char_option_count = strlen(app->alphabet);
+    if(char_option_count < 0) {
+        return;
+    }
+
+    // determine largest character value that avoids bias
+    char ceil = CHAR_MAX - (CHAR_MAX % char_option_count) - 1;
+
+    // iteratively fill the password buffer with random values
+    // then keep only values that are in-range (no bias)
+    void* remaining_buffer = app->password;
+    size_t remaining_length = (app->length * sizeof(char));
+
+    while(remaining_length != 0) {
+        // fewer calls to hardware TRNG is more efficient
+        furi_hal_random_fill_buf(remaining_buffer, remaining_length);
+
+        // keep only values that are in-range (no bias)
+        char* target = remaining_buffer;
+        char* source = remaining_buffer;
+        size_t valid_count = 0;
+
+        for(size_t i = 0; i < remaining_length; i++) {
+            int v = *source;
+            // if the generated random value is in range, keep it
+            if(v < ceil) {
+                v %= char_option_count;
+                *target = app->alphabet[v];
+                // increment target pointer and count of valid items found
+                target++;
+                valid_count++;
+            }
+            // always increment the source pointer
+            source++;
+        }
+        remaining_length -= valid_count;
+        remaining_buffer = target;
     }
-    app->password[app->length] = '\0';
 }
 
 void update_password(PassGen* app, bool vibro) {

+ 1 - 1
apps_source_code/flipperzero-slots/application.fam

@@ -12,6 +12,6 @@ App(
     fap_icon_assets="assets",
     fap_author="@Daniel-dev-s",
     fap_weburl="https://github.com/Daniel-dev-s/flipperzero-slots",
-    fap_version="1.0",
+    fap_version="1.1",
     fap_description="Simple Slots simulator game",
 )

+ 37 - 33
apps_source_code/flipperzero-slots/slotmachine.c

@@ -222,42 +222,46 @@ int32_t slotmachine_app(void* p) {
     InputEvent input;
 
     // endless input cycle
-    while(furi_message_queue_get(slotmachine->input_queue, &input, FuriWaitForever) ==
-          FuriStatusOk) {
-        // if thread idle - take it
-        furi_check(furi_mutex_acquire(slotmachine->model_mutex, FuriWaitForever) == FuriStatusOk);
-
-        if(!checkIsSpinning(slotmachine)) {
-            if(input.key == InputKeyBack) {
-                // exit on back button
-                furi_mutex_release(slotmachine->model_mutex);
-                break;
-            } else if(input.key == InputKeyOk && input.type == InputTypeShort && slotmachine->winview) {
-                slotmachine->winview = false;
-            } else if(
-                input.key == InputKeyOk && input.type == InputTypeShort &&
-                slotmachine->bet <= slotmachine->money) {
-                COLUMNS_COUNT = rand() % 3 + 2;
-                slotmachine->money -= slotmachine->bet;
-                slotmachine->columns[0]->spining = true;
-
-                for(int i = 0; i < COLUMNS_COUNT; i++) {
-                    slotmachine->columns[i]->times = DEFAULT_SPINNING_TIMES;
-                    slotmachine->columns[i]->speed = DEFAULT_SPEED;
-                }
-            } else if(input.key == InputKeyUp) {
-                if(slotmachine->bet + 10 < slotmachine->money) {
-                    slotmachine->bet += 10;
-                }
-            } else if(input.key == InputKeyDown) {
-                if(slotmachine->bet - 10 > 0) {
-                    slotmachine->bet -= 10;
+    while(1) {
+        if(furi_message_queue_get(slotmachine->input_queue, &input, 100) == FuriStatusOk) {
+            // if thread idle - take it
+            furi_check(
+                furi_mutex_acquire(slotmachine->model_mutex, FuriWaitForever) == FuriStatusOk);
+
+            if(!checkIsSpinning(slotmachine)) {
+                if(input.key == InputKeyBack) {
+                    // exit on back button
+                    furi_mutex_release(slotmachine->model_mutex);
+                    break;
+                } else if(
+                    input.key == InputKeyOk && input.type == InputTypeShort &&
+                    slotmachine->winview) {
+                    slotmachine->winview = false;
+                } else if(
+                    input.key == InputKeyOk && input.type == InputTypeShort &&
+                    slotmachine->bet <= slotmachine->money) {
+                    COLUMNS_COUNT = rand() % 3 + 2;
+                    slotmachine->money -= slotmachine->bet;
+                    slotmachine->columns[0]->spining = true;
+
+                    for(int i = 0; i < COLUMNS_COUNT; i++) {
+                        slotmachine->columns[i]->times = DEFAULT_SPINNING_TIMES;
+                        slotmachine->columns[i]->speed = DEFAULT_SPEED;
+                    }
+                } else if(input.key == InputKeyUp) {
+                    if(slotmachine->bet + 10 < slotmachine->money) {
+                        slotmachine->bet += 10;
+                    }
+                } else if(input.key == InputKeyDown) {
+                    if(slotmachine->bet - 10 > 0) {
+                        slotmachine->bet -= 10;
+                    }
                 }
             }
-        }
 
-        // release thread
-        furi_mutex_release(slotmachine->model_mutex);
+            // release thread
+            furi_mutex_release(slotmachine->model_mutex);
+        }
         // redraw viewport
         view_port_update(slotmachine->view_port);
     }

+ 1 - 1
apps_source_code/fz-reaction-game/application.fam

@@ -9,6 +9,6 @@ App(
     fap_icon="icon.png",
     fap_author="@Milk-Cool",
     fap_weburl="https://github.com/Milk-Cool/fz-reaction-game",
-    fap_version="1.0",
+    fap_version="1.1",
     fap_description="A simple reaction test game",
 )

+ 1 - 0
apps_source_code/fz-reaction-game/reaction.c

@@ -85,6 +85,7 @@ int32_t reaction_main(void* p) {
             if(state == 0 && event.type == InputTypePress && event.key == InputKeyOk) {
                 state = 1;
                 time = 0;
+                view_port_update(view_port);
                 int t = rand() % 6000 + 1000;
                 furi_delay_ms(t);
                 furi_timer_start(timer_stop, t);

+ 1 - 1
apps_source_code/gpio_7segment/application.fam

@@ -9,6 +9,6 @@ App(
     fap_category="GPIO",
     fap_author="@jamisonderek",
     fap_weburl="https://github.com/jamisonderek/flipper-zero-tutorials/tree/main/gpio",
-    fap_version="1.0",
+    fap_version="1.1",
     fap_description="Control a 7-segment display with GPIO pins",
 )

+ 6 - 1
apps_source_code/gpio_7segment/gpio_7segment_app.c

@@ -227,7 +227,11 @@ int32_t gpio_7segment_app(void* p) {
                     FURI_LOG_I(TAG, "OK pressed.");
                     if(furi_mutex_acquire(context->mutex, FuriWaitForever) == FuriStatusOk) {
                         // Pick a random number between 1 and 6...
-                        context->data->digit = (furi_hal_random_get() % 6) + 1;
+                        if(context->data->digit >= 9) {
+                            context->data->digit = 0;
+                        } else {
+                            context->data->digit += 1;
+                        }
 
                         gpio_7segment_show(context->data->digit, context->data->invert);
                         furi_mutex_release(context->mutex);
@@ -252,6 +256,7 @@ int32_t gpio_7segment_app(void* p) {
             // We had an issue getting message from the queue, so exit application.
             processing = false;
         }
+        view_port_update(view_port);
     } while(processing);
 
     // Disconnect the GPIO pins.

+ 1 - 1
apps_source_code/reversi/application.fam

@@ -14,6 +14,6 @@ App(
     fap_icon_assets_symbol="game_reversi",
     fap_author="@dimat",
     fap_weburl="https://github.com/zyuhel/flipperzero-racegame",
-    fap_version="1.0",
+    fap_version="1.1",
     fap_description="Reversi game, the game controls should be intuitive. Longs press on OK opens the menu to start a new game.",
 )

+ 2 - 1
apps_source_code/reversi/game_reversi.c

@@ -321,7 +321,7 @@ int32_t game_reversi_app() {
            (app_state.game.current_player != app_state.game.human_color)) {
             computer_move(&app_state.game);
         }
-        FuriStatus event_status = furi_message_queue_get(event_queue, &input, FuriWaitForever);
+        FuriStatus event_status = furi_message_queue_get(event_queue, &input, 100);
         if(event_status == FuriStatusOk) {
             // handle only press event, ignore repeat/release events
 
@@ -341,6 +341,7 @@ int32_t game_reversi_app() {
             view_port_update(view_port);
             furi_mutex_release(app_state.mutex);
         }
+        view_port_update(view_port);
     }
 
     gui_remove_view_port(gui, view_port);

+ 1 - 1
apps_source_code/rubiks_cube_scrambler/application.fam

@@ -19,6 +19,6 @@ App(
     fap_icon="cube.png",
     fap_author="@RaZeSloth",
     fap_weburl="https://github.com/RaZeSloth/flipperzero-rubiks-cube-scrambler",
-    fap_version="1.0",
+    fap_version="1.1",
     fap_description="App generates random moves to scramble a Rubik's cube.",
 )

+ 1 - 0
apps_source_code/rubiks_cube_scrambler/rubiks_cube_scrambler.c

@@ -103,6 +103,7 @@ int32_t rubiks_cube_scrambler_main(void* p) {
         if(event.key == InputKeyBack) {
             break;
         }
+        view_port_update(view_port);
     }
 
     furi_message_queue_free(event_queue);

+ 1 - 1
apps_source_code/servotester/application.fam

@@ -12,6 +12,6 @@ App(
     fap_category="GPIO",
     fap_author="Alexander Semion",
     fap_weburl="https://github.com/spin7ion/flipper-servotester",
-    fap_version="1.0",
+    fap_version="1.1",
     fap_description="Application uses A7 pin for servo PWM output. Has different modes: Manual, Center, Auto.",
 )

+ 3 - 0
apps_source_code/servotester/servotester.c

@@ -145,6 +145,7 @@ int32_t servotester_app(void* p) {
                 if(pWidth <= 1990) pWidth += 10;
                 servotester_update_pwm();
             }
+            view_port_update(view_port);
         } else if(event.type == EventTypeTick) {
             if(mode == Auto) {
                 pWidth += dir;
@@ -153,7 +154,9 @@ int32_t servotester_app(void* p) {
                 }
                 servotester_update_pwm();
             }
+            view_port_update(view_port);
         }
+        view_port_update(view_port);
     }
 
     furi_hal_power_disable_otg();

+ 1 - 1
apps_source_code/sony-intervalometer/application.fam

@@ -11,6 +11,6 @@ App(
     fap_category="Infrared",
     fap_author="@Nitepone",
     fap_weburl="https://github.com/Nitepone/flipper-intervalometer",
-    fap_version="1.0",
+    fap_version="1.1",
     fap_description="This is a simple configurable valometer app for Sony cameras. Works via Infrared port.",
 )

+ 2 - 0
apps_source_code/sony-intervalometer/intervalometer.c

@@ -632,6 +632,8 @@ int32_t flipvalo_app() {
 
     next_event:
         furi_mutex_release(fv_priv->mutex);
+
+        view_port_update(view_port);
     }
 
 cleanup:

+ 1 - 1
apps_source_code/t-rex-runner/application.fam

@@ -12,6 +12,6 @@ App(
     order=36,
     fap_author="@Rrycbarm",
     fap_weburl="https://github.com/Rrycbarm/t-rex-runner",
-    fap_version="1.1",
+    fap_version="1.2",
     fap_description="Play the port of the Chrome browser T-Rex game on your Flipper Zero.",
 )

+ 16 - 8
apps_source_code/t-rex-runner/trexrunner.c

@@ -192,6 +192,17 @@ static void game_state_init(GameState* const game_state) {
     game_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
 }
 
+static void game_state_reinit(GameState* const game_state) {
+    game_state->last_tick = furi_get_tick();
+    game_state->y_acceleration = game_state->y_speed = 0;
+    game_state->y_position = DINO_START_Y;
+    game_state->has_cactus = 0;
+    game_state->background_position = 0;
+    game_state->lost = 0;
+    game_state->x_speed = START_x_speed;
+    game_state->score = 0;
+}
+
 int32_t trexrunner_app() {
     FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent));
 
@@ -218,7 +229,7 @@ int32_t trexrunner_app() {
     gui_add_view_port(gui, view_port, GuiLayerFullscreen);
 
     PluginEvent event;
-    for(bool processing = true; processing && !game_state->lost;) {
+    for(bool processing = true; processing;) {
         FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
         if(event_status == FuriStatusOk) {
             // press events
@@ -234,6 +245,10 @@ int32_t trexrunner_app() {
                     case InputKeyRight:
                         break;
                     case InputKeyOk:
+                        if(game_state->lost) {
+                            game_state_reinit(game_state);
+                            break;
+                        }
                         if(game_state->y_position == DINO_START_Y)
                             game_state->y_speed = JUMP_SPEED;
                         break;
@@ -246,13 +261,6 @@ int32_t trexrunner_app() {
                     }
                 }
             }
-        } else {
-            // event timeout
-            ;
-        }
-        if(game_state->lost) {
-            furi_message_queue_get(
-                event_queue, &event, 1500); //Sleep to show  the "you lost" message
         }
         view_port_update(view_port);
         furi_mutex_release(game_state->mutex);

+ 1 - 1
apps_source_code/timelapse/application.fam

@@ -10,7 +10,7 @@ App(
     fap_icon_assets="icons",
     fap_icon="zeitraffer.png",
     fap_category="GPIO",
-    fap_version="1.0",
+    fap_version="1.1",
     fap_description="Simple intervalometer app, works via GPIO pins.",
     fap_author="Aurelius Rosenbaum",
     fap_weburl="https://github.com/theageoflove/flipperzero-zeitraffer",

+ 3 - 0
apps_source_code/timelapse/zeitraffer.c

@@ -325,6 +325,7 @@ int32_t zeitraffer_app(void* p) {
                     }
                 }
             }
+            view_port_update(view_port);
         }
 
         // Наше событие — это сработавший таймер
@@ -378,6 +379,8 @@ int32_t zeitraffer_app(void* p) {
             default:
                 notification_message(notifications, &sequence_display_backlight_enforce_auto);
             }
+
+            view_port_update(view_port);
         }
         if(Time < 1) Time = 1; // Не даём открутить таймер меньше единицы
         if(Count < -1)

+ 1 - 1
main_apps_sources/hex_viewer/application.fam

@@ -13,6 +13,6 @@ App(
     fap_category="Tools",
     fap_icon_assets="icons",
     fap_author="@QtRoS",
-    fap_version="1.0",
+    fap_version="1.1",
     fap_description="App allows to view various files as HEX.",
 )

+ 51 - 46
main_apps_sources/hex_viewer/hex_viewer.c

@@ -229,53 +229,58 @@ int32_t hex_viewer_app(void* p) {
         hex_viewer_read_file(hex_viewer);
 
         InputEvent input;
-        while(furi_message_queue_get(hex_viewer->input_queue, &input, FuriWaitForever) ==
-              FuriStatusOk) {
-            if(input.key == InputKeyBack) {
-                break;
-            } else if(input.key == InputKeyUp) {
-                furi_check(furi_mutex_acquire(hex_viewer->mutex, FuriWaitForever) == FuriStatusOk);
-                if(hex_viewer->model->file_offset > 0) {
-                    hex_viewer->model->file_offset -= HEX_VIEWER_BYTES_PER_LINE;
-                    if(!hex_viewer_read_file(hex_viewer)) break;
-                }
-                furi_mutex_release(hex_viewer->mutex);
-            } else if(input.key == InputKeyDown) {
-                furi_check(furi_mutex_acquire(hex_viewer->mutex, FuriWaitForever) == FuriStatusOk);
-                uint32_t last_byte_on_screen =
-                    hex_viewer->model->file_offset + hex_viewer->model->file_read_bytes;
-
-                if(hex_viewer->model->file_size > last_byte_on_screen) {
-                    hex_viewer->model->file_offset += HEX_VIEWER_BYTES_PER_LINE;
-                    if(!hex_viewer_read_file(hex_viewer)) break;
+        while(1) {
+            if(furi_message_queue_get(hex_viewer->input_queue, &input, 100) == FuriStatusOk) {
+                if(input.key == InputKeyBack) {
+                    break;
+                } else if(input.key == InputKeyUp) {
+                    furi_check(
+                        furi_mutex_acquire(hex_viewer->mutex, FuriWaitForever) == FuriStatusOk);
+                    if(hex_viewer->model->file_offset > 0) {
+                        hex_viewer->model->file_offset -= HEX_VIEWER_BYTES_PER_LINE;
+                        if(!hex_viewer_read_file(hex_viewer)) break;
+                    }
+                    furi_mutex_release(hex_viewer->mutex);
+                } else if(input.key == InputKeyDown) {
+                    furi_check(
+                        furi_mutex_acquire(hex_viewer->mutex, FuriWaitForever) == FuriStatusOk);
+                    uint32_t last_byte_on_screen =
+                        hex_viewer->model->file_offset + hex_viewer->model->file_read_bytes;
+
+                    if(hex_viewer->model->file_size > last_byte_on_screen) {
+                        hex_viewer->model->file_offset += HEX_VIEWER_BYTES_PER_LINE;
+                        if(!hex_viewer_read_file(hex_viewer)) break;
+                    }
+                    furi_mutex_release(hex_viewer->mutex);
+                } else if(input.key == InputKeyLeft) {
+                    furi_check(
+                        furi_mutex_acquire(hex_viewer->mutex, FuriWaitForever) == FuriStatusOk);
+                    hex_viewer->model->mode = !hex_viewer->model->mode;
+                    furi_mutex_release(hex_viewer->mutex);
+                } else if(input.key == InputKeyRight) {
+                    FuriString* buffer;
+                    buffer = furi_string_alloc();
+                    furi_string_printf(
+                        buffer,
+                        "File path: %s\nFile size: %lu (0x%lX)",
+                        furi_string_get_cstr(file_path),
+                        hex_viewer->model->file_size,
+                        hex_viewer->model->file_size);
+
+                    DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
+                    DialogMessage* message = dialog_message_alloc();
+                    dialog_message_set_header(
+                        message, "Hex Viewer v1.1", 16, 2, AlignLeft, AlignTop);
+                    dialog_message_set_icon(message, &I_hex_10px, 3, 2);
+                    dialog_message_set_text(
+                        message, furi_string_get_cstr(buffer), 3, 16, AlignLeft, AlignTop);
+                    dialog_message_set_buttons(message, NULL, NULL, "Back");
+                    dialog_message_show(dialogs, message);
+
+                    furi_string_free(buffer);
+                    dialog_message_free(message);
+                    furi_record_close(RECORD_DIALOGS);
                 }
-                furi_mutex_release(hex_viewer->mutex);
-            } else if(input.key == InputKeyLeft) {
-                furi_check(furi_mutex_acquire(hex_viewer->mutex, FuriWaitForever) == FuriStatusOk);
-                hex_viewer->model->mode = !hex_viewer->model->mode;
-                furi_mutex_release(hex_viewer->mutex);
-            } else if(input.key == InputKeyRight) {
-                FuriString* buffer;
-                buffer = furi_string_alloc();
-                furi_string_printf(
-                    buffer,
-                    "File path: %s\nFile size: %lu (0x%lX)",
-                    furi_string_get_cstr(file_path),
-                    hex_viewer->model->file_size,
-                    hex_viewer->model->file_size);
-
-                DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
-                DialogMessage* message = dialog_message_alloc();
-                dialog_message_set_header(message, "Hex Viewer v1.1", 16, 2, AlignLeft, AlignTop);
-                dialog_message_set_icon(message, &I_hex_10px, 3, 2);
-                dialog_message_set_text(
-                    message, furi_string_get_cstr(buffer), 3, 16, AlignLeft, AlignTop);
-                dialog_message_set_buttons(message, NULL, NULL, "Back");
-                dialog_message_show(dialogs, message);
-
-                furi_string_free(buffer);
-                dialog_message_free(message);
-                furi_record_close(RECORD_DIALOGS);
             }
 
             view_port_update(hex_viewer->view_port);

+ 1 - 1
main_apps_sources/ir_scope/application.fam

@@ -8,6 +8,6 @@ App(
     fap_icon="ir_scope.png",
     fap_category="Infrared",
     fap_author="@kallanreed",
-    fap_version="1.1",
+    fap_version="1.2",
     fap_description="App allows to see incoming IR signals.",
 )

+ 23 - 22
main_apps_sources/ir_scope/ir_scope.c

@@ -140,30 +140,31 @@ int32_t ir_scope_app(void* p) {
 
     InputEvent event;
     bool processing = true;
-    while(processing &&
-          furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk) {
-        if(event.type == InputTypeRelease) {
-            furi_mutex_acquire(state.mutex, FuriWaitForever);
-
-            if(event.key == InputKeyBack) {
-                processing = false;
-            } else if(event.key == InputKeyUp) {
-                state.us_per_sample = MIN(1000, state.us_per_sample + 25);
-                state.autoscale = false;
-            } else if(event.key == InputKeyDown) {
-                state.us_per_sample = MAX(25, state.us_per_sample - 25);
-                state.autoscale = false;
-            } else if(event.key == InputKeyOk) {
-                state.autoscale = !state.autoscale;
-                if(state.autoscale)
-                    state_set_autoscale(&state);
-                else
-                    state.us_per_sample = 200;
+    while(processing) {
+        if(furi_message_queue_get(event_queue, &event, 100) == FuriStatusOk) {
+            if(event.type == InputTypeRelease) {
+                furi_mutex_acquire(state.mutex, FuriWaitForever);
+
+                if(event.key == InputKeyBack) {
+                    processing = false;
+                } else if(event.key == InputKeyUp) {
+                    state.us_per_sample = MIN(1000, state.us_per_sample + 25);
+                    state.autoscale = false;
+                } else if(event.key == InputKeyDown) {
+                    state.us_per_sample = MAX(25, state.us_per_sample - 25);
+                    state.autoscale = false;
+                } else if(event.key == InputKeyOk) {
+                    state.autoscale = !state.autoscale;
+                    if(state.autoscale)
+                        state_set_autoscale(&state);
+                    else
+                        state.us_per_sample = 200;
+                }
+
+                furi_mutex_release(state.mutex);
             }
-
-            view_port_update(view_port);
-            furi_mutex_release(state.mutex);
         }
+        view_port_update(view_port);
     }
 
     // Clean up.

+ 1 - 1
main_apps_sources/text_viewer/application.fam

@@ -13,6 +13,6 @@ App(
     fap_category="Tools",
     fap_icon_assets="icons",
     fap_author="@kowalski7cc & @kyhwana",
-    fap_version="1.0",
+    fap_version="1.1",
     fap_description="Text viewer application",
 )

+ 51 - 49
main_apps_sources/text_viewer/text_viewer.c

@@ -223,56 +223,58 @@ int32_t text_viewer_app(void* p) {
         text_viewer_read_file(text_viewer);
 
         InputEvent input;
-        while(furi_message_queue_get(text_viewer->input_queue, &input, FuriWaitForever) ==
-              FuriStatusOk) {
-            if(input.key == InputKeyBack) {
-                break;
-            } else if(input.key == InputKeyUp) {
-                furi_check(
-                    furi_mutex_acquire(text_viewer->mutex, FuriWaitForever) == FuriStatusOk);
-                if(text_viewer->model->file_offset > 0) {
-                    text_viewer->model->file_offset -= TEXT_VIEWER_BYTES_PER_LINE;
-                    if(!text_viewer_read_file(text_viewer)) break;
-                }
-                furi_mutex_release(text_viewer->mutex);
-            } else if(input.key == InputKeyDown) {
-                furi_check(
-                    furi_mutex_acquire(text_viewer->mutex, FuriWaitForever) == FuriStatusOk);
-                uint32_t last_byte_on_screen =
-                    text_viewer->model->file_offset + text_viewer->model->file_read_bytes;
-
-                if(text_viewer->model->file_size > last_byte_on_screen) {
-                    text_viewer->model->file_offset += TEXT_VIEWER_BYTES_PER_LINE;
-                    if(!text_viewer_read_file(text_viewer)) break;
+        while(1) {
+            if(furi_message_queue_get(text_viewer->input_queue, &input, 100) == FuriStatusOk) {
+                if(input.key == InputKeyBack) {
+                    break;
+                } else if(input.key == InputKeyUp) {
+                    furi_check(
+                        furi_mutex_acquire(text_viewer->mutex, FuriWaitForever) == FuriStatusOk);
+                    if(text_viewer->model->file_offset > 0) {
+                        text_viewer->model->file_offset -= TEXT_VIEWER_BYTES_PER_LINE;
+                        if(!text_viewer_read_file(text_viewer)) break;
+                    }
+                    furi_mutex_release(text_viewer->mutex);
+                } else if(input.key == InputKeyDown) {
+                    furi_check(
+                        furi_mutex_acquire(text_viewer->mutex, FuriWaitForever) == FuriStatusOk);
+                    uint32_t last_byte_on_screen =
+                        text_viewer->model->file_offset + text_viewer->model->file_read_bytes;
+
+                    if(text_viewer->model->file_size > last_byte_on_screen) {
+                        text_viewer->model->file_offset += TEXT_VIEWER_BYTES_PER_LINE;
+                        if(!text_viewer_read_file(text_viewer)) break;
+                    }
+                    furi_mutex_release(text_viewer->mutex);
+                } else if(input.key == InputKeyLeft) {
+                    furi_check(
+                        furi_mutex_acquire(text_viewer->mutex, FuriWaitForever) == FuriStatusOk);
+                    text_viewer->model->mode = !text_viewer->model->mode;
+                    furi_mutex_release(text_viewer->mutex);
+                } else if(input.key == InputKeyRight) {
+                    FuriString* buffer;
+                    buffer = furi_string_alloc();
+                    furi_string_printf(
+                        buffer,
+                        "File path: %s\nFile size: %lu (0x%lX)",
+                        furi_string_get_cstr(file_path),
+                        text_viewer->model->file_size,
+                        text_viewer->model->file_size);
+
+                    DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
+                    DialogMessage* message = dialog_message_alloc();
+                    dialog_message_set_header(
+                        message, "Text Viewer v1.1", 16, 2, AlignLeft, AlignTop);
+                    dialog_message_set_icon(message, &I_text_10px, 3, 2);
+                    dialog_message_set_text(
+                        message, furi_string_get_cstr(buffer), 3, 16, AlignLeft, AlignTop);
+                    dialog_message_set_buttons(message, NULL, NULL, "Back");
+                    dialog_message_show(dialogs, message);
+
+                    furi_string_free(buffer);
+                    dialog_message_free(message);
+                    furi_record_close(RECORD_DIALOGS);
                 }
-                furi_mutex_release(text_viewer->mutex);
-            } else if(input.key == InputKeyLeft) {
-                furi_check(
-                    furi_mutex_acquire(text_viewer->mutex, FuriWaitForever) == FuriStatusOk);
-                text_viewer->model->mode = !text_viewer->model->mode;
-                furi_mutex_release(text_viewer->mutex);
-            } else if(input.key == InputKeyRight) {
-                FuriString* buffer;
-                buffer = furi_string_alloc();
-                furi_string_printf(
-                    buffer,
-                    "File path: %s\nFile size: %lu (0x%lX)",
-                    furi_string_get_cstr(file_path),
-                    text_viewer->model->file_size,
-                    text_viewer->model->file_size);
-
-                DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
-                DialogMessage* message = dialog_message_alloc();
-                dialog_message_set_header(message, "Text Viewer v1.1", 16, 2, AlignLeft, AlignTop);
-                dialog_message_set_icon(message, &I_text_10px, 3, 2);
-                dialog_message_set_text(
-                    message, furi_string_get_cstr(buffer), 3, 16, AlignLeft, AlignTop);
-                dialog_message_set_buttons(message, NULL, NULL, "Back");
-                dialog_message_show(dialogs, message);
-
-                furi_string_free(buffer);
-                dialog_message_free(message);
-                furi_record_close(RECORD_DIALOGS);
             }
             view_port_update(text_viewer->view_port);
         }

+ 1 - 0
non_catalog_apps/ServoTesterApp/app.c

@@ -244,6 +244,7 @@ int32_t servotester_app_entry(void* p) {
                 }
             }
         }
+        view_port_update(app->view_port);
     }
 
     furi_timer_free(timer);

+ 67 - 66
non_catalog_apps/flipperzero-qrcode/qrcode_app.c

@@ -546,81 +546,82 @@ int32_t qrcode_app(void* p) {
         }
 
         InputEvent input;
-        while(furi_message_queue_get(instance->input_queue, &input, FuriWaitForever) ==
-              FuriStatusOk) {
-            furi_check(furi_mutex_acquire(instance->mutex, FuriWaitForever) == FuriStatusOk);
-
-            if(input.key == InputKeyBack) {
-                if(instance->message) {
-                    furi_string_free(instance->message);
-                    instance->message = NULL;
-                }
-                if(instance->qrcode) {
-                    qrcode_free(instance->qrcode);
-                    instance->qrcode = NULL;
-                }
-                instance->loading = true;
-                instance->edit = false;
-                furi_mutex_release(instance->mutex);
-                break;
-            } else if(input.key == InputKeyRight) {
-                instance->show_stats = true;
-            } else if(input.key == InputKeyLeft) {
-                instance->show_stats = false;
-            } else if(instance->show_stats && !instance->loading && instance->qrcode) {
-                if(input.key == InputKeyUp) {
-                    if(!instance->edit) {
-                        instance->selected_idx = MAX(0, instance->selected_idx - 1);
-                    } else {
-                        if(instance->selected_idx == 0 &&
-                           instance->set_version < MAX_QRCODE_VERSION) {
-                            instance->set_version++;
-                        } else if(instance->selected_idx == 1) {
-                            uint8_t max_ecc = instance->set_version == instance->min_version ?
-                                                  instance->max_ecc_at_min_version :
-                                                  ECC_HIGH;
-                            if(instance->set_ecc < max_ecc) {
-                                instance->set_ecc++;
-                            }
-                        }
+        while(1) {
+            if(furi_message_queue_get(instance->input_queue, &input, 100) == FuriStatusOk) {
+                furi_check(furi_mutex_acquire(instance->mutex, FuriWaitForever) == FuriStatusOk);
+
+                if(input.key == InputKeyBack) {
+                    if(instance->message) {
+                        furi_string_free(instance->message);
+                        instance->message = NULL;
                     }
-                } else if(input.key == InputKeyDown) {
-                    if(!instance->edit) {
-                        instance->selected_idx = MIN(1, instance->selected_idx + 1);
-                    } else {
-                        if(instance->selected_idx == 0 &&
-                           instance->set_version > instance->min_version) {
-                            instance->set_version--;
-                            if(instance->set_version == instance->min_version) {
-                                instance->set_ecc =
-                                    MAX(instance->set_ecc, instance->max_ecc_at_min_version);
+                    if(instance->qrcode) {
+                        qrcode_free(instance->qrcode);
+                        instance->qrcode = NULL;
+                    }
+                    instance->loading = true;
+                    instance->edit = false;
+                    furi_mutex_release(instance->mutex);
+                    break;
+                } else if(input.key == InputKeyRight) {
+                    instance->show_stats = true;
+                } else if(input.key == InputKeyLeft) {
+                    instance->show_stats = false;
+                } else if(instance->show_stats && !instance->loading && instance->qrcode) {
+                    if(input.key == InputKeyUp) {
+                        if(!instance->edit) {
+                            instance->selected_idx = MAX(0, instance->selected_idx - 1);
+                        } else {
+                            if(instance->selected_idx == 0 &&
+                               instance->set_version < MAX_QRCODE_VERSION) {
+                                instance->set_version++;
+                            } else if(instance->selected_idx == 1) {
+                                uint8_t max_ecc = instance->set_version == instance->min_version ?
+                                                      instance->max_ecc_at_min_version :
+                                                      ECC_HIGH;
+                                if(instance->set_ecc < max_ecc) {
+                                    instance->set_ecc++;
+                                }
                             }
-                        } else if(instance->selected_idx == 1 && instance->set_ecc > 0) {
-                            instance->set_ecc--;
                         }
-                    }
-                } else if(input.key == InputKeyOk) {
-                    if(instance->edit && (instance->set_version != instance->qrcode->version ||
-                                          instance->set_ecc != instance->qrcode->ecc)) {
-                        QRCode* qrcode = instance->qrcode;
-                        instance->loading = true;
-
-                        if(rebuild_qrcode(instance, instance->set_version, instance->set_ecc)) {
-                            qrcode_free(qrcode);
+                    } else if(input.key == InputKeyDown) {
+                        if(!instance->edit) {
+                            instance->selected_idx = MIN(1, instance->selected_idx + 1);
                         } else {
-                            FURI_LOG_E(TAG, "Could not rebuild qrcode");
-                            instance->qrcode = qrcode;
-                            instance->set_version = qrcode->version;
-                            instance->set_ecc = qrcode->ecc;
+                            if(instance->selected_idx == 0 &&
+                               instance->set_version > instance->min_version) {
+                                instance->set_version--;
+                                if(instance->set_version == instance->min_version) {
+                                    instance->set_ecc =
+                                        MAX(instance->set_ecc, instance->max_ecc_at_min_version);
+                                }
+                            } else if(instance->selected_idx == 1 && instance->set_ecc > 0) {
+                                instance->set_ecc--;
+                            }
                         }
+                    } else if(input.key == InputKeyOk) {
+                        if(instance->edit && (instance->set_version != instance->qrcode->version ||
+                                              instance->set_ecc != instance->qrcode->ecc)) {
+                            QRCode* qrcode = instance->qrcode;
+                            instance->loading = true;
+
+                            if(rebuild_qrcode(instance, instance->set_version, instance->set_ecc)) {
+                                qrcode_free(qrcode);
+                            } else {
+                                FURI_LOG_E(TAG, "Could not rebuild qrcode");
+                                instance->qrcode = qrcode;
+                                instance->set_version = qrcode->version;
+                                instance->set_ecc = qrcode->ecc;
+                            }
 
-                        instance->loading = false;
+                            instance->loading = false;
+                        }
+                        instance->edit = !instance->edit;
                     }
-                    instance->edit = !instance->edit;
                 }
-            }
 
-            furi_mutex_release(instance->mutex);
+                furi_mutex_release(instance->mutex);
+            }
             view_port_update(instance->view_port);
         }
 

+ 1 - 0
non_catalog_apps/ir_remote/infrared_remote_app.c

@@ -529,6 +529,7 @@ int32_t infrared_remote_app(void* p) {
                     is_transmitting = true;
                 }
             }
+            view_port_update(app->view_port);
         }
     }
 

+ 1 - 0
non_catalog_apps/memsic_2125/memsic_2125_app.c

@@ -208,6 +208,7 @@ int32_t memsic_2125_app(void* p) {
             // We had an issue getting message from the queue, so exit application.
             processing = false;
         }
+        view_port_update(view_port);
     } while(processing);
 
     // Free resources

+ 4 - 0
non_catalog_apps/rcwl_0516/rcwl_0516.c

@@ -77,6 +77,9 @@ void rcwl_0516_free(Rcwl_0516* app) {
     furi_hal_light_set(LightBlue, 0);
     furi_hal_light_set(LightRed, 0);
     furi_hal_light_set(LightGreen, 0);
+
+    furi_hal_gpio_init(app->input_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
+    furi_hal_gpio_init(app->output_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
 }
 
 int32_t rcwl_0516(void* p) {
@@ -93,6 +96,7 @@ int32_t rcwl_0516(void* p) {
                 if(event.type == InputTypePress) break;
             }
         }
+        view_port_update(app->view_port);
     }
 
     rcwl_0516_free(app);

+ 0 - 15
non_catalog_apps/solitaire/application.fam

@@ -1,15 +0,0 @@
-App(
-    appid="solitaire",
-    name="Solitaire",
-    apptype=FlipperAppType.EXTERNAL,
-    entry_point="solitaire_app",
-    requires=["gui","storage","canvas"],
-    stack_size=2 * 1024,
-    order=30,
-    fap_icon="solitaire_10px.png",
-    fap_category="Games",
-    fap_icon_assets="assets",
-    fap_author="@teeebor",
-    fap_version="1.0",
-    fap_description="Solitaire game",
-)

BIN
non_catalog_apps/solitaire/assets/card_graphics.png


BIN
non_catalog_apps/solitaire/assets/solitaire_main.png


+ 0 - 353
non_catalog_apps/solitaire/common/card.c

@@ -1,353 +0,0 @@
-#include "card.h"
-#include "dml.h"
-#include "ui.h"
-
-#define CARD_DRAW_X_START 108
-#define CARD_DRAW_Y_START 38
-#define CARD_DRAW_X_SPACE 10
-#define CARD_DRAW_Y_SPACE 8
-#define CARD_DRAW_X_OFFSET 4
-#define CARD_DRAW_FIRST_ROW_LENGTH 7
-
-uint8_t pips[4][3] = {
-    {21, 10, 7}, //spades
-    {7, 10, 7}, //hearts
-    {0, 10, 7}, //diamonds
-    {14, 10, 7}, //clubs
-};
-uint8_t letters[13][3] = {
-    {0, 0, 5},
-    {5, 0, 5},
-    {10, 0, 5},
-    {15, 0, 5},
-    {20, 0, 5},
-    {25, 0, 5},
-    {30, 0, 5},
-    {0, 5, 5},
-    {5, 5, 5},
-    {10, 5, 5},
-    {15, 5, 5},
-    {20, 5, 5},
-    {25, 5, 5},
-};
-
-//region Player card positions
-uint8_t playerCardPositions[22][4] = {
-    //first row
-    {108, 38},
-    {98, 38},
-    {88, 38},
-    {78, 38},
-    {68, 38},
-    {58, 38},
-    {48, 38},
-    {38, 38},
-    //second row
-    {104, 26},
-    {94, 26},
-    {84, 26},
-    {74, 26},
-    {64, 26},
-    {54, 26},
-    {44, 26},
-    //third row
-    {99, 14},
-    {89, 14},
-    {79, 14},
-    {69, 14},
-    {59, 14},
-    {49, 14},
-};
-//endregion
-Icon* card_graphics = NULL;
-
-void set_card_graphics(const Icon* graphics) {
-    card_graphics = (Icon*)graphics;
-}
-
-void draw_card_at_colored(
-    int8_t pos_x,
-    int8_t pos_y,
-    uint8_t pip,
-    uint8_t character,
-    bool inverted,
-    Canvas* const canvas) {
-    DrawMode primary = inverted ? Black : White;
-    DrawMode secondary = inverted ? White : Black;
-    draw_rounded_box(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, primary);
-    draw_rounded_box_frame(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, Black);
-
-    uint8_t* drawInfo = pips[pip];
-    uint8_t px = drawInfo[0], py = drawInfo[1], s = drawInfo[2];
-
-    uint8_t left = pos_x + 2;
-    uint8_t right = (pos_x + CARD_WIDTH - s - 2);
-    uint8_t top = pos_y + 2;
-    uint8_t bottom = (pos_y + CARD_HEIGHT - s - 2);
-
-    draw_icon_clip(canvas, card_graphics, right, top, px, py, s, s, secondary);
-    draw_icon_clip_flipped(canvas, card_graphics, left, bottom, px, py, s, s, secondary);
-
-    drawInfo = letters[character];
-    px = drawInfo[0], py = drawInfo[1], s = drawInfo[2];
-    left = pos_x + 2;
-    right = (pos_x + CARD_WIDTH - s - 2);
-    top = pos_y + 2;
-    bottom = (pos_y + CARD_HEIGHT - s - 2);
-
-    draw_icon_clip(canvas, card_graphics, left, top + 1, px, py, s, s, secondary);
-    draw_icon_clip_flipped(canvas, card_graphics, right, bottom - 1, px, py, s, s, secondary);
-}
-
-void draw_card_at(int8_t pos_x, int8_t pos_y, uint8_t pip, uint8_t character, Canvas* const canvas) {
-    draw_card_at_colored(pos_x, pos_y, pip, character, false, canvas);
-}
-
-void draw_deck(const Card* cards, uint8_t count, Canvas* const canvas) {
-    for(int i = count - 1; i >= 0; i--) {
-        draw_card_at(
-            playerCardPositions[i][0],
-            playerCardPositions[i][1],
-            cards[i].pip,
-            cards[i].character,
-            canvas);
-    }
-}
-
-Vector card_pos_at_index(uint8_t index) {
-    return (Vector){playerCardPositions[index][0], playerCardPositions[index][1]};
-}
-
-void draw_card_back_at(int8_t pos_x, int8_t pos_y, Canvas* const canvas) {
-    draw_rounded_box(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, White);
-    draw_rounded_box_frame(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, Black);
-
-    draw_icon_clip(canvas, card_graphics, pos_x + 1, pos_y + 1, 35, 0, 15, 21, Black);
-}
-
-void generate_deck(Deck* deck_ptr, uint8_t deck_count) {
-    uint16_t counter = 0;
-    if(deck_ptr->cards != NULL) {
-        free(deck_ptr->cards);
-    }
-
-    deck_ptr->deck_count = deck_count;
-    deck_ptr->card_count = deck_count * 52;
-    deck_ptr->cards = malloc(sizeof(Card) * deck_ptr->card_count);
-
-    for(uint8_t deck = 0; deck < deck_count; deck++) {
-        for(uint8_t pip = 0; pip < 4; pip++) {
-            for(uint8_t label = 0; label < 13; label++) {
-                deck_ptr->cards[counter] = (Card){pip, label, false, false};
-                counter++;
-            }
-        }
-    }
-}
-
-void shuffle_deck(Deck* deck_ptr) {
-    srand(DWT->CYCCNT);
-    deck_ptr->index = 0;
-    int max = deck_ptr->deck_count * 52;
-    for(int i = 0; i < max; i++) {
-        int r = i + (rand() % (max - i));
-        Card tmp = deck_ptr->cards[i];
-        deck_ptr->cards[i] = deck_ptr->cards[r];
-        deck_ptr->cards[r] = tmp;
-    }
-}
-
-uint8_t hand_count(const Card* cards, uint8_t count) {
-    uint8_t aceCount = 0;
-    uint8_t score = 0;
-
-    for(uint8_t i = 0; i < count; i++) {
-        if(cards[i].character == 12)
-            aceCount++;
-        else {
-            if(cards[i].character > 8)
-                score += 10;
-            else
-                score += cards[i].character + 2;
-        }
-    }
-
-    for(uint8_t i = 0; i < aceCount; i++) {
-        if((score + 11) <= 21)
-            score += 11;
-        else
-            score++;
-    }
-
-    return score;
-}
-
-void draw_card_animation(
-    Card animatingCard,
-    Vector from,
-    Vector control,
-    Vector to,
-    float t,
-    bool extra_margin,
-    Canvas* const canvas) {
-    float time = t;
-    if(extra_margin) {
-        time += 0.2;
-    }
-
-    Vector currentPos = quadratic_2d(from, control, to, time);
-    if(t > 1) {
-        draw_card_at(
-            currentPos.x, currentPos.y, animatingCard.pip, animatingCard.character, canvas);
-    } else {
-        if(t < 0.5)
-            draw_card_back_at(currentPos.x, currentPos.y, canvas);
-        else
-            draw_card_at(
-                currentPos.x, currentPos.y, animatingCard.pip, animatingCard.character, canvas);
-    }
-}
-
-void init_hand(Hand* hand_ptr, uint8_t count) {
-    hand_ptr->cards = malloc(sizeof(Card) * count);
-    hand_ptr->index = 0;
-    hand_ptr->max = count;
-}
-
-void free_hand(Hand* hand_ptr) {
-    FURI_LOG_D("CARD", "Freeing hand");
-    free(hand_ptr->cards);
-}
-
-void add_to_hand(Hand* hand_ptr, Card card) {
-    FURI_LOG_D("CARD", "Adding to hand");
-    if(hand_ptr->index < hand_ptr->max) {
-        hand_ptr->cards[hand_ptr->index] = card;
-        hand_ptr->index++;
-    }
-}
-
-void draw_card_space(int16_t pos_x, int16_t pos_y, bool highlighted, Canvas* const canvas) {
-    if(highlighted) {
-        draw_rounded_box_frame(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, Black);
-        draw_rounded_box_frame(
-            canvas, pos_x + 2, pos_y + 2, CARD_WIDTH - 4, CARD_HEIGHT - 4, White);
-    } else {
-        draw_rounded_box(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, Black);
-        draw_rounded_box_frame(
-            canvas, pos_x + 2, pos_y + 2, CARD_WIDTH - 4, CARD_HEIGHT - 4, White);
-    }
-}
-
-int first_non_flipped_card(Hand hand) {
-    for(int i = 0; i < hand.index; i++) {
-        if(!hand.cards[i].flipped) {
-            return i;
-        }
-    }
-    return hand.index;
-}
-
-void draw_hand_column(
-    Hand hand,
-    int16_t pos_x,
-    int16_t pos_y,
-    int8_t highlight,
-    Canvas* const canvas) {
-    if(hand.index == 0) {
-        draw_card_space(pos_x, pos_y, highlight > 0, canvas);
-        if(highlight == 0)
-            draw_rounded_box(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, Inverse);
-        return;
-    }
-
-    int loopEnd = hand.index;
-    int hStart = max(loopEnd - 4, 0);
-    int pos = 0;
-    int first = first_non_flipped_card(hand);
-    bool wastop = false;
-    if(first >= 0 && first <= hStart && highlight != first) {
-        if(first > 0) {
-            draw_card_back_at(pos_x, pos_y + pos, canvas);
-            pos += 4;
-            hStart++;
-            wastop = true;
-        }
-        draw_card_at_colored(
-            pos_x, pos_y + pos, hand.cards[first].pip, hand.cards[first].character, false, canvas);
-        pos += 8;
-        hStart++;
-    }
-    if(hStart > highlight && highlight >= 0) {
-        if(!wastop && first > 0) {
-            draw_card_back_at(pos_x, pos_y + pos, canvas);
-            pos += 4;
-            hStart++;
-        }
-        draw_card_at_colored(
-            pos_x,
-            pos_y + pos,
-            hand.cards[highlight].pip,
-            hand.cards[highlight].character,
-            true,
-            canvas);
-        pos += 8;
-        hStart++;
-    }
-    for(int i = hStart; i < loopEnd; i++, pos += 4) {
-        if(hand.cards[i].flipped) {
-            draw_card_back_at(pos_x, pos_y + pos, canvas);
-            if(i == highlight)
-                draw_rounded_box(
-                    canvas, pos_x + 1, pos_y + pos + 1, CARD_WIDTH - 2, CARD_HEIGHT - 2, Inverse);
-        } else {
-            draw_card_at_colored(
-                pos_x,
-                pos_y + pos,
-                hand.cards[i].pip,
-                hand.cards[i].character,
-                (i == highlight),
-                canvas);
-            if(i == highlight || i == first) pos += 4;
-        }
-    }
-}
-
-Card remove_from_deck(uint16_t index, Deck* deck) {
-    FURI_LOG_D("CARD", "Removing from deck");
-    Card result = {0, 0, true, false};
-    if(deck->card_count > 0) {
-        deck->card_count--;
-        for(int i = 0, curr_index = 0; i <= deck->card_count; i++) {
-            if(i != index) {
-                deck->cards[curr_index] = deck->cards[i];
-                curr_index++;
-            } else {
-                result = deck->cards[i];
-            }
-        }
-        if(deck->index >= 0) {
-            deck->index--;
-        }
-    }
-    return result;
-}
-
-void extract_hand_region(Hand* hand, Hand* to, uint8_t start_index) {
-    FURI_LOG_D("CARD", "Extracting hand region");
-    if(start_index >= hand->index) return;
-
-    for(uint8_t i = start_index; i < hand->index; i++) {
-        add_to_hand(to, hand->cards[i]);
-    }
-    hand->index = start_index;
-}
-
-void add_hand_region(Hand* to, Hand* from) {
-    FURI_LOG_D("CARD", "Adding hand region");
-    if((to->index + from->index) <= to->max) {
-        for(int i = 0; i < from->index; i++) {
-            add_to_hand(to, from->cards[i]);
-        }
-    }
-}

+ 0 - 192
non_catalog_apps/solitaire/common/card.h

@@ -1,192 +0,0 @@
-#pragma once
-
-#include <gui/gui.h>
-#include <math.h>
-#include <stdlib.h>
-#include "dml.h"
-
-#define CARD_HEIGHT 23
-#define CARD_HALF_HEIGHT 11
-#define CARD_WIDTH 17
-#define CARD_HALF_WIDTH 8
-
-//region types
-typedef struct {
-    uint8_t pip; //Pip index 0:spades, 1:hearths, 2:diamonds, 3:clubs
-    uint8_t character; //Card letter [0-12], 0 means 2, 12 is Ace
-    bool disabled;
-    bool flipped;
-} Card;
-
-typedef struct {
-    uint8_t deck_count; //Number of decks used
-    Card* cards; //Cards in the deck
-    int card_count;
-    int index; //Card index (to know where we at in the deck)
-} Deck;
-
-typedef struct {
-    Card* cards; //Cards in the deck
-    uint8_t index; //Current index
-    uint8_t max; //How many cards we want to store
-} Hand;
-//endregion
-
-void set_card_graphics(const Icon* graphics);
-
-/**
- * Gets card coordinates at the index (range: 0-20).
- *
- * @param index Index to check 0-20
- * @return      Position of the card
- */
-Vector card_pos_at_index(uint8_t index);
-
-/**
- * Draws card at a given coordinate (top-left corner)
- *
- * @param pos_x         X position
- * @param pos_y         Y position
- * @param pip           Pip index 0:spades, 1:hearths, 2:diamonds, 3:clubs
- * @param character     Letter [0-12] 0 is 2, 12 is A
- * @param canvas        Pointer to Flipper's canvas object
- */
-void draw_card_at(int8_t pos_x, int8_t pos_y, uint8_t pip, uint8_t character, Canvas* const canvas);
-
-/**
- * Draws card at a given coordinate (top-left corner)
- *
- * @param pos_x         X position
- * @param pos_y         Y position
- * @param pip           Pip index 0:spades, 1:hearths, 2:diamonds, 3:clubs
- * @param character     Letter [0-12] 0 is 2, 12 is A
- * @param inverted      Invert colors
- * @param canvas        Pointer to Flipper's canvas object
- */
-void draw_card_at_colored(
-    int8_t pos_x,
-    int8_t pos_y,
-    uint8_t pip,
-    uint8_t character,
-    bool inverted,
-    Canvas* const canvas);
-
-/**
- * Draws 'count' cards at the bottom right corner
- *
- * @param cards     List of cards
- * @param count     Count of cards
- * @param canvas    Pointer to Flipper's canvas object
- */
-void draw_deck(const Card* cards, uint8_t count, Canvas* const canvas);
-
-/**
- * Draws card back at a given coordinate (top-left corner)
- *
- * @param pos_x     X coordinate
- * @param pos_y     Y coordinate
- * @param canvas    Pointer to Flipper's canvas object
- */
-void draw_card_back_at(int8_t pos_x, int8_t pos_y, Canvas* const canvas);
-
-/**
- * Generates the deck
- *
- * @param deck_ptr      Pointer to the deck
- * @param deck_count    Number of decks
- */
-void generate_deck(Deck* deck_ptr, uint8_t deck_count);
-
-/**
- * Shuffles the deck
- *
- * @param deck_ptr Pointer to the deck
- */
-void shuffle_deck(Deck* deck_ptr);
-
-/**
- * Calculates the hand count for blackjack
- *
- * @param cards     List of cards
- * @param count     Count of cards
- * @return          Hand value
- */
-uint8_t hand_count(const Card* cards, uint8_t count);
-
-/**
- * Draws card animation
- *
- * @param animatingCard Card to animate
- * @param from          Starting position
- * @param control       Quadratic lerp control point
- * @param to            End point
- * @param t             Current time (0-1)
- * @param extra_margin  Use extra margin at the end (arrives 0.2 unit before the end so it can stay there a bit)
- * @param canvas        Pointer to Flipper's canvas object
- */
-void draw_card_animation(
-    Card animatingCard,
-    Vector from,
-    Vector control,
-    Vector to,
-    float t,
-    bool extra_margin,
-    Canvas* const canvas);
-
-/**
- * Init hand pointer
- * @param hand_ptr   Pointer to hand
- * @param count      Number of cards we want to store
- */
-void init_hand(Hand* hand_ptr, uint8_t count);
-
-/**
- * Free hand resources
- * @param hand_ptr  Pointer to hand
- */
-void free_hand(Hand* hand_ptr);
-
-/**
- * Add card to hand
- * @param hand_ptr  Pointer to hand
- * @param card      Card to add
- */
-void add_to_hand(Hand* hand_ptr, Card card);
-
-/**
- * Draw card placement position at coordinate
- * @param pos_x     X coordinate
- * @param pos_y     Y coordinate
- * @param highlighted   Apply highlight effect
- * @param canvas    Canvas object
- */
-void draw_card_space(int16_t pos_x, int16_t pos_y, bool highlighted, Canvas* const canvas);
-
-/**
- * Draws a column of card, displaying the last [max_cards] cards on the list
- * @param hand              Hand object
- * @param pos_x             X coordinate to draw
- * @param pos_y             Y coordinate to draw
- * @param highlight         Index to highlight, negative means no highlight
- * @param canvas            Canvas object
- */
-void draw_hand_column(
-    Hand hand,
-    int16_t pos_x,
-    int16_t pos_y,
-    int8_t highlight,
-    Canvas* const canvas);
-
-/**
- * Removes a card from the deck (Be aware, if you remove the first item, the deck index will be at -1 so you have to handle that)
- * @param index Index to remove
- * @param deck  Deck reference
- * @return      The removed card
- */
-Card remove_from_deck(uint16_t index, Deck* deck);
-
-int first_non_flipped_card(Hand hand);
-
-void extract_hand_region(Hand* hand, Hand* to, uint8_t start_index);
-
-void add_hand_region(Hand* to, Hand* from);

+ 0 - 53
non_catalog_apps/solitaire/common/dml.c

@@ -1,53 +0,0 @@
-#include "dml.h"
-#include <math.h>
-
-float lerp(float v0, float v1, float t) {
-    if(t > 1) return v1;
-    return (1 - t) * v0 + t * v1;
-}
-
-Vector lerp_2d(Vector start, Vector end, float t) {
-    return (Vector){
-        lerp(start.x, end.x, t),
-        lerp(start.y, end.y, t),
-    };
-}
-
-Vector quadratic_2d(Vector start, Vector control, Vector end, float t) {
-    return lerp_2d(lerp_2d(start, control, t), lerp_2d(control, end, t), t);
-}
-
-Vector vector_add(Vector a, Vector b) {
-    return (Vector){a.x + b.x, a.y + b.y};
-}
-
-Vector vector_sub(Vector a, Vector b) {
-    return (Vector){a.x - b.x, a.y - b.y};
-}
-
-Vector vector_mul_components(Vector a, Vector b) {
-    return (Vector){a.x * b.x, a.y * b.y};
-}
-
-Vector vector_div_components(Vector a, Vector b) {
-    return (Vector){a.x / b.x, a.y / b.y};
-}
-
-Vector vector_normalized(Vector a) {
-    float length = vector_magnitude(a);
-    return (Vector){a.x / length, a.y / length};
-}
-
-float vector_magnitude(Vector a) {
-    return sqrt(a.x * a.x + a.y * a.y);
-}
-
-float vector_distance(Vector a, Vector b) {
-    return vector_magnitude(vector_sub(a, b));
-}
-
-float vector_dot(Vector a, Vector b) {
-    Vector _a = vector_normalized(a);
-    Vector _b = vector_normalized(b);
-    return _a.x * _b.x + _a.y * _b.y;
-}

+ 0 - 116
non_catalog_apps/solitaire/common/dml.h

@@ -1,116 +0,0 @@
-//
-// Doofy's Math library
-//
-
-#pragma once
-
-typedef struct {
-    float x;
-    float y;
-} Vector;
-
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#define max(a, b) ((a) > (b) ? (a) : (b))
-#define abs(x) ((x) > 0 ? (x) : -(x))
-
-/**
- * Lerp function
- *
- * @param v0    Start value
- * @param v1    End value
- * @param t     Time (0-1 range)
- * @return      Point between v0-v1 at a given time
- */
-float lerp(float v0, float v1, float t);
-
-/**
- * 2D lerp function
- *
- * @param start Start vector
- * @param end   End vector
- * @param t     Time (0-1 range)
- * @return      2d Vector between start and end at time
- */
-Vector lerp_2d(Vector start, Vector end, float t);
-
-/**
- * Quadratic lerp function
- *
- * @param start     Start vector
- * @param control   Control point
- * @param end       End vector
- * @param t         Time (0-1 range)
- * @return          2d Vector at time
- */
-Vector quadratic_2d(Vector start, Vector control, Vector end, float t);
-
-/**
- * Add vector components together
- *
- * @param a     First vector
- * @param b     Second vector
- * @return      Resulting vector
- */
-Vector vector_add(Vector a, Vector b);
-
-/**
- * Subtract vector components together
- *
- * @param a First vector
- * @param b Second vector
- * @return  Resulting vector
- */
-Vector vector_sub(Vector a, Vector b);
-
-/**
- * Multiplying vector components together
- *
- * @param a First vector
- * @param b Second vector
- * @return  Resulting vector
- */
-Vector vector_mul_components(Vector a, Vector b);
-
-/**
- * Dividing vector components
- *
- * @param a First vector
- * @param b Second vector
- * @return  Resulting vector
- */
-Vector vector_div_components(Vector a, Vector b);
-
-/**
- * Calculating Vector length
- *
- * @param a Direction vector
- * @return  Length of the vector
- */
-float vector_magnitude(Vector a);
-
-/**
- * Get a normalized vector (length of 1)
- *
- * @param a Direction vector
- * @return  Normalized vector
- */
-Vector vector_normalized(Vector a);
-
-/**
- * Calculate two vector's distance
- *
- * @param a First vector
- * @param b Second vector
- * @return  Distance between vectors
- */
-float vector_distance(Vector a, Vector b);
-
-/**
- * Calculate the dot product of the vectors.
- * No need to normalize, it will do it
- *
- * @param a First vector
- * @param b Second vector
- * @return  value from -1 to 1
- */
-float vector_dot(Vector a, Vector b);

+ 0 - 103
non_catalog_apps/solitaire/common/menu.c

@@ -1,103 +0,0 @@
-#include "menu.h"
-
-void add_menu(Menu* menu, const char* name, void (*callback)(void*)) {
-    MenuItem* items = menu->items;
-
-    menu->items = malloc(sizeof(MenuItem) * (menu->menu_count + 1));
-    for(uint8_t i = 0; i < menu->menu_count; i++) {
-        menu->items[i] = items[i];
-    }
-    free(items);
-
-    menu->items[menu->menu_count] = (MenuItem){name, true, callback};
-    menu->menu_count++;
-}
-
-void free_menu(Menu* menu) {
-    free(menu->items);
-    free(menu);
-}
-
-void set_menu_state(Menu* menu, uint8_t index, bool state) {
-    if(menu->menu_count > index) {
-        menu->items[index].enabled = state;
-    }
-    if(!state && menu->current_menu == index) move_menu(menu, 1);
-}
-
-void move_menu(Menu* menu, int8_t direction) {
-    if(!menu->enabled) return;
-    int max = menu->menu_count;
-    for(int8_t i = 0; i < max; i++) {
-        FURI_LOG_D(
-            "MENU",
-            "Iteration %i, current %i, direction %i, state %i",
-            i,
-            menu->current_menu,
-            direction,
-            menu->items[menu->current_menu].enabled ? 1 : 0);
-        if(direction < 0 && menu->current_menu == 0) {
-            menu->current_menu = menu->menu_count - 1;
-        } else {
-            menu->current_menu = (menu->current_menu + direction) % menu->menu_count;
-        }
-        FURI_LOG_D(
-            "MENU",
-            "After process current %i, direction %i, state %i",
-            menu->current_menu,
-            direction,
-            menu->items[menu->current_menu].enabled ? 1 : 0);
-        if(menu->items[menu->current_menu].enabled) {
-            FURI_LOG_D("MENU", "Next menu %i", menu->current_menu);
-            return;
-        }
-    }
-    FURI_LOG_D("MENU", "Not found, setting false");
-    menu->enabled = false;
-}
-
-void activate_menu(Menu* menu, void* state) {
-    if(!menu->enabled) return;
-    menu->items[menu->current_menu].callback(state);
-}
-
-void render_menu(Menu* menu, Canvas* canvas, uint8_t pos_x, uint8_t pos_y) {
-    if(!menu->enabled) return;
-    canvas_set_color(canvas, ColorWhite);
-    canvas_draw_rbox(canvas, pos_x, pos_y, menu->menu_width + 2, 10, 2);
-
-    uint8_t w = pos_x + menu->menu_width;
-    uint8_t h = pos_y + 10;
-    uint8_t p1x = pos_x + 2;
-    uint8_t p2x = pos_x + menu->menu_width - 2;
-    uint8_t p1y = pos_y + 2;
-    uint8_t p2y = pos_y + 8;
-
-    canvas_set_color(canvas, ColorBlack);
-    canvas_draw_line(canvas, p1x, pos_y, p2x, pos_y);
-    canvas_draw_line(canvas, p1x, h, p2x, h);
-    canvas_draw_line(canvas, pos_x, p1y, pos_x, p2y);
-    canvas_draw_line(canvas, w, p1y, w, p2y);
-    canvas_draw_dot(canvas, pos_x + 1, pos_y + 1);
-    canvas_draw_dot(canvas, w - 1, pos_y + 1);
-    canvas_draw_dot(canvas, w - 1, h - 1);
-    canvas_draw_dot(canvas, pos_x + 1, h - 1);
-
-    //    canvas_draw_rbox(canvas, pos_x, pos_y, menu->menu_width + 2, 10, 2);
-    canvas_set_font(canvas, FontSecondary);
-    canvas_draw_str_aligned(
-        canvas,
-        pos_x + menu->menu_width / 2,
-        pos_y + 6,
-        AlignCenter,
-        AlignCenter,
-        menu->items[menu->current_menu].name);
-    //9*5
-    int center = pos_x + menu->menu_width / 2;
-    for(uint8_t i = 0; i < 4; i++) {
-        for(int8_t j = -i; j <= i; j++) {
-            canvas_draw_dot(canvas, center + j, pos_y - 4 + i);
-            canvas_draw_dot(canvas, center + j, pos_y + 14 - i);
-        }
-    }
-}

+ 0 - 77
non_catalog_apps/solitaire/common/menu.h

@@ -1,77 +0,0 @@
-#pragma once
-
-#include <furi.h>
-#include <gui/gui.h>
-
-typedef struct {
-    const char* name; //Name of the menu
-    bool enabled; //Is the menu item enabled (it will not render, you cannot select it)
-
-    void (*callback)(
-        void* state); //Callback for when the activate_menu is called while this menu is selected
-} MenuItem;
-
-typedef struct {
-    MenuItem* items; //list of menu items
-    uint8_t menu_count; //count of menu items (do not change)
-    uint8_t current_menu; //currently selected menu item
-    uint8_t menu_width; //width of the menu
-    bool enabled; //is the menu enabled (it will not render and accept events when disabled)
-} Menu;
-
-/**
- * Cleans up the pointers used by the menu
- *
- * @param menu Pointer of the menu to clean up
- */
-void free_menu(Menu* menu);
-
-/**
- * Add a new menu item
- *
- * @param menu      Pointer of the menu
- * @param name      Name of the menu item
- * @param callback  Callback called on activation
- */
-void add_menu(Menu* menu, const char* name, void (*callback)(void*));
-
-/**
- * Setting menu item to be enabled/disabled
- *
- * @param menu  Pointer of the menu
- * @param index Menu index to set
- * @param state Enabled (true), Disabled(false)
- */
-void set_menu_state(Menu* menu, uint8_t index, bool state);
-
-/**
- * Moves selection up or down
- *
- * @param menu      Pointer of the menu
- * @param direction Direction to move -1 down, 1 up
- */
-void move_menu(Menu* menu, int8_t direction);
-
-/**
- * Triggers the current menu callback
- *
- * @param menu  Pointer of the menu
- * @param state Usually your application state
- */
-void activate_menu(Menu* menu, void* state);
-
-/**
- * Renders the menu at a coordinate (call it in your render function).
- *
- * Keep in mind that Flipper has a 128x64 pixel screen resolution and the coordinate
- * you give is the menu's rectangle top-left corner (arrows not included).
- * The rectangle height is 10 px, the arrows have a 4 pixel height. Space needed is 18px.
- * The width of the menu can be configured in the menu object.
- *
- *
- * @param menu      Pointer of the menu
- * @param canvas    Flippers Canvas pointer
- * @param pos_x     X position to draw
- * @param pos_y     Y position to draw
- */
-void render_menu(Menu* menu, Canvas* canvas, uint8_t pos_x, uint8_t pos_y);

+ 0 - 69
non_catalog_apps/solitaire/common/queue.c

@@ -1,69 +0,0 @@
-#include "queue.h"
-
-void render_queue(const QueueState* queue_state, const void* app_state, Canvas* const canvas) {
-    if(queue_state->current != NULL && queue_state->current->render != NULL)
-        ((QueueItem*)queue_state->current)->render(app_state, canvas);
-}
-
-bool run_queue(QueueState* queue_state, void* app_state) {
-    if(queue_state->current != NULL) {
-        queue_state->running = true;
-        if((furi_get_tick() - queue_state->start) >= queue_state->current->duration)
-            dequeue(queue_state, app_state);
-
-        return true;
-    }
-    return false;
-}
-
-void dequeue(QueueState* queue_state, void* app_state) {
-    ((QueueItem*)queue_state->current)->callback(app_state);
-    QueueItem* f = queue_state->current;
-    queue_state->current = f->next;
-    free(f);
-    if(queue_state->current != NULL) {
-        if(queue_state->current->start != NULL) queue_state->current->start(app_state);
-        queue_state->start = furi_get_tick();
-    } else {
-        queue_state->running = false;
-    }
-}
-
-void queue_clear(QueueState* queue_state) {
-    queue_state->running = false;
-    QueueItem* curr = queue_state->current;
-    while(curr != NULL) {
-        QueueItem* f = curr;
-        curr = curr->next;
-        free(f);
-    }
-}
-
-void enqueue(
-    QueueState* queue_state,
-    void* app_state,
-    void (*done)(void* state),
-    void (*start)(void* state),
-    void (*render)(const void* state, Canvas* const canvas),
-    uint32_t duration) {
-    QueueItem* next;
-    if(queue_state->current == NULL) {
-        queue_state->start = furi_get_tick();
-        queue_state->current = malloc(sizeof(QueueItem));
-        next = queue_state->current;
-        if(next->start != NULL) next->start(app_state);
-
-    } else {
-        next = queue_state->current;
-        while(next->next != NULL) {
-            next = (QueueItem*)(next->next);
-        }
-        next->next = malloc(sizeof(QueueItem));
-        next = next->next;
-    }
-    next->callback = done;
-    next->render = render;
-    next->start = start;
-    next->duration = duration;
-    next->next = NULL;
-}

+ 0 - 70
non_catalog_apps/solitaire/common/queue.h

@@ -1,70 +0,0 @@
-#pragma once
-
-#include <gui/gui.h>
-#include <furi.h>
-
-typedef struct {
-    void (*callback)(void* state); //Callback for when the item is dequeued
-    void (*render)(
-        const void* state,
-        Canvas* const canvas); //Callback for the rendering loop while this item is running
-    void (*start)(void* state); //Callback when this item is started running
-    void* next; //Pointer to the next item
-    uint32_t duration; //duration of the item
-} QueueItem;
-
-typedef struct {
-    unsigned int start; //current queue item start time
-    QueueItem* current; //current queue item
-    bool running; //is the queue running
-} QueueState;
-
-/**
- * Enqueue a new item.
- *
- * @param queue_state   The queue state pointer
- * @param app_state     Your app state
- * @param done          Callback for dequeue event
- * @param start         Callback for when the item is activated
- * @param render        Callback to render loop if needed
- * @param duration      Length of the item
- */
-void enqueue(
-    QueueState* queue_state,
-    void* app_state,
-    void (*done)(void* state),
-    void (*start)(void* state),
-    void (*render)(const void* state, Canvas* const canvas),
-    uint32_t duration);
-/**
- * Clears all queue items
- *
- * @param queue_state   The queue state pointer
- */
-void queue_clear(QueueState* queue_state);
-
-/**
- * Dequeues the active queue item. Usually you don't need to call it directly.
- *
- * @param queue_state   The queue state pointer
- * @param app_state     Your application state
- */
-void dequeue(QueueState* queue_state, void* app_state);
-
-/**
- * Runs the queue logic (place it in your tick function)
- *
- * @param queue_state   The queue state pointer
- * @param app_state     Your application state
- * @return              FALSE when there is nothing to run, TRUE otherwise
- */
-bool run_queue(QueueState* queue_state, void* app_state);
-
-/**
- * Calls the currently active queue items render callback (if there is any)
- *
- * @param queue_state   The queue state pointer
- * @param app_state     Your application state
- * @param canvas        Pointer to Flipper's canvas object
- */
-void render_queue(const QueueState* queue_state, const void* app_state, Canvas* const canvas);

+ 0 - 257
non_catalog_apps/solitaire/common/ui.c

@@ -1,257 +0,0 @@
-#include "ui.h"
-#include <gui/canvas_i.h>
-#include <u8g2_glue.h>
-#include <gui/icon_animation_i.h>
-#include <gui/icon.h>
-#include <gui/icon_i.h>
-#include <furi_hal.h>
-
-TileMap* tileMap;
-uint8_t tileMapCount = 0;
-
-void ui_cleanup() {
-    if(tileMap != NULL) {
-        for(uint8_t i = 0; i < tileMapCount; i++) {
-            if(tileMap[i].data != NULL) free(tileMap[i].data);
-        }
-        free(tileMap);
-    }
-}
-
-void add_new_tilemap(uint8_t* data, unsigned long iconId) {
-    TileMap* old = tileMap;
-    tileMapCount++;
-    tileMap = malloc(sizeof(TileMap) * tileMapCount);
-    if(tileMapCount > 1) {
-        for(uint8_t i = 0; i < tileMapCount; i++) tileMap[i] = old[i];
-    }
-    tileMap[tileMapCount - 1] = (TileMap){data, iconId};
-}
-
-uint8_t* get_tilemap(unsigned long icon_id) {
-    for(uint8_t i = 0; i < tileMapCount; i++) {
-        if(tileMap[i].iconId == icon_id) return tileMap[i].data;
-    }
-
-    return NULL;
-}
-
-uint32_t pixel_index(uint8_t x, uint8_t y) {
-    return y * SCREEN_WIDTH + x;
-}
-
-bool in_screen(int16_t x, int16_t y) {
-    return x >= 0 && x < SCREEN_WIDTH && y >= 0 && y < SCREEN_HEIGHT;
-}
-
-unsigned flipBit(uint8_t x, uint8_t bit) {
-    return x ^ (1 << bit);
-}
-
-unsigned setBit(uint8_t x, uint8_t bit) {
-    return x | (1 << bit);
-}
-
-unsigned unsetBit(uint8_t x, uint8_t bit) {
-    return x & ~(1 << bit);
-}
-
-bool test_pixel(uint8_t* data, uint8_t x, uint8_t y, uint8_t w) {
-    uint8_t current_bit = (y % 8);
-    uint8_t current_row = ((y - current_bit) / 8);
-    uint8_t current_value = data[current_row * w + x];
-    return current_value & (1 << current_bit);
-}
-
-uint8_t* get_buffer(Canvas* const canvas) {
-    return canvas->fb.tile_buf_ptr;
-    //  return canvas_get_buffer(canvas);
-}
-uint8_t* make_buffer() {
-    return malloc(sizeof(uint8_t) * 8 * 128);
-}
-void clone_buffer(uint8_t* canvas, uint8_t* data) {
-    for(int i = 0; i < 1024; i++) {
-        data[i] = canvas[i];
-    }
-}
-
-bool read_pixel(Canvas* const canvas, int16_t x, int16_t y) {
-    if(in_screen(x, y)) {
-        return test_pixel(get_buffer(canvas), x, y, SCREEN_WIDTH);
-    }
-    return false;
-}
-
-void set_pixel(Canvas* const canvas, int16_t x, int16_t y, DrawMode draw_mode) {
-    if(in_screen(x, y)) {
-        uint8_t current_bit = (y % 8);
-        uint8_t current_row = ((y - current_bit) / 8);
-        uint32_t i = pixel_index(x, current_row);
-        uint8_t* buffer = get_buffer(canvas);
-
-        uint8_t current_value = buffer[i];
-        if(draw_mode == Inverse) {
-            buffer[i] = flipBit(current_value, current_bit);
-        } else {
-            if(draw_mode == White) {
-                buffer[i] = unsetBit(current_value, current_bit);
-            } else {
-                buffer[i] = setBit(current_value, current_bit);
-            }
-        }
-    }
-}
-
-void draw_line(
-    Canvas* const canvas,
-    int16_t x1,
-    int16_t y1,
-    int16_t x2,
-    int16_t y2,
-    DrawMode draw_mode) {
-    for(int16_t x = x2; x >= x1; x--) {
-        for(int16_t y = y2; y >= y1; y--) {
-            set_pixel(canvas, x, y, draw_mode);
-        }
-    }
-}
-
-void draw_rounded_box_frame(
-    Canvas* const canvas,
-    int16_t x,
-    int16_t y,
-    uint8_t w,
-    uint8_t h,
-    DrawMode draw_mode) {
-    int16_t xMinCorner = x + 1;
-    int16_t xMax = x + w - 1;
-    int16_t xMaxCorner = x + w - 2;
-    int16_t yMinCorner = y + 1;
-    int16_t yMax = y + h - 1;
-    int16_t yMaxCorner = y + h - 2;
-    draw_line(canvas, xMinCorner, y, xMaxCorner, y, draw_mode);
-    draw_line(canvas, xMinCorner, yMax, xMaxCorner, yMax, draw_mode);
-    draw_line(canvas, x, yMinCorner, x, yMaxCorner, draw_mode);
-    draw_line(canvas, xMax, yMinCorner, xMax, yMaxCorner, draw_mode);
-}
-
-void draw_rounded_box(
-    Canvas* const canvas,
-    int16_t x,
-    int16_t y,
-    uint8_t w,
-    uint8_t h,
-    DrawMode draw_mode) {
-    for(int16_t o = w - 2; o >= 1; o--) {
-        for(int16_t p = h - 2; p >= 1; p--) {
-            set_pixel(canvas, x + o, y + p, draw_mode);
-        }
-    }
-    draw_rounded_box_frame(canvas, x, y, w, h, draw_mode);
-}
-
-void invert_shape(Canvas* const canvas, uint8_t* data, int16_t x, int16_t y, uint8_t w, uint8_t h) {
-    draw_pixels(canvas, data, x, y, w, h, Inverse);
-}
-
-void draw_pixels(
-    Canvas* const canvas,
-    uint8_t* data,
-    int16_t x,
-    int16_t y,
-    uint8_t w,
-    uint8_t h,
-    DrawMode drawMode) {
-    for(int8_t o = 0; o < w; o++) {
-        for(int8_t p = 0; p < h; p++) {
-            if(in_screen(o + x, p + y) && data[p * w + o] == 1)
-                set_pixel(canvas, o + x, p + y, drawMode);
-        }
-    }
-}
-
-void draw_rectangle(
-    Canvas* const canvas,
-    int16_t x,
-    int16_t y,
-    uint8_t w,
-    uint8_t h,
-    DrawMode drawMode) {
-    for(int8_t o = 0; o < w; o++) {
-        for(int8_t p = 0; p < h; p++) {
-            if(in_screen(o + x, p + y)) {
-                set_pixel(canvas, o + x, p + y, drawMode);
-            }
-        }
-    }
-}
-
-void invert_rectangle(Canvas* const canvas, int16_t x, int16_t y, uint8_t w, uint8_t h) {
-    draw_rectangle(canvas, x, y, w, h, Inverse);
-}
-
-uint8_t* image_data(Canvas* const canvas, const Icon* icon) {
-    uint8_t* data = malloc(sizeof(uint8_t) * 8 * 128);
-    uint8_t* screen = canvas->fb.tile_buf_ptr;
-    canvas->fb.tile_buf_ptr = data;
-    canvas_draw_icon(canvas, 0, 0, icon);
-    canvas->fb.tile_buf_ptr = screen;
-    return data;
-}
-
-uint8_t* getOrAddIconData(Canvas* const canvas, const Icon* icon) {
-    uint8_t* icon_data = get_tilemap((unsigned long)icon);
-    if(icon_data == NULL) {
-        icon_data = image_data(canvas, icon);
-        add_new_tilemap(icon_data, (unsigned long)icon);
-    }
-    return icon_data;
-}
-
-void draw_icon_clip(
-    Canvas* const canvas,
-    const Icon* icon,
-    int16_t x,
-    int16_t y,
-    uint8_t left,
-    uint8_t top,
-    uint8_t w,
-    uint8_t h,
-    DrawMode drawMode) {
-    uint8_t* icon_data = getOrAddIconData(canvas, icon);
-
-    for(int i = 0; i < w; i++) {
-        for(int j = 0; j < h; j++) {
-            bool on = test_pixel(icon_data, left + i, top + j, SCREEN_WIDTH);
-            if(drawMode == Filled) {
-                set_pixel(canvas, x + i, y + j, on ? Black : White);
-            } else if(on)
-                set_pixel(canvas, x + i, y + j, drawMode);
-        }
-    }
-}
-
-void draw_icon_clip_flipped(
-    Canvas* const canvas,
-    const Icon* icon,
-    int16_t x,
-    int16_t y,
-    uint8_t left,
-    uint8_t top,
-    uint8_t w,
-    uint8_t h,
-    DrawMode drawMode) {
-    uint8_t* icon_data = getOrAddIconData(canvas, icon);
-
-    for(int i = 0; i < w; i++) {
-        for(int j = 0; j < h; j++) {
-            bool on = test_pixel(icon_data, left + i, top + j, SCREEN_WIDTH);
-
-            if(drawMode == Filled) {
-                set_pixel(canvas, x + w - i - 1, y + h - j - 1, on ? Black : White);
-            } else if(on)
-                set_pixel(canvas, x + w - i - 1, y + h - j - 1, drawMode);
-        }
-    }
-}

+ 0 - 105
non_catalog_apps/solitaire/common/ui.h

@@ -1,105 +0,0 @@
-#pragma once
-
-#include <furi.h>
-#include <gui/canvas.h>
-
-#define SCREEN_WIDTH 128
-#define SCREEN_HEIGHT 64
-
-typedef enum {
-    Black,
-    White,
-    Inverse,
-    Filled //Currently only for Icon clip drawing
-} DrawMode;
-
-// size is the screen size
-
-typedef struct {
-    uint8_t* data;
-    unsigned long iconId;
-} TileMap;
-
-bool test_pixel(uint8_t* data, uint8_t x, uint8_t y, uint8_t w);
-
-uint8_t* image_data(Canvas* const canvas, const Icon* icon);
-
-uint32_t pixel_index(uint8_t x, uint8_t y);
-
-void draw_icon_clip(
-    Canvas* const canvas,
-    const Icon* icon,
-    int16_t x,
-    int16_t y,
-    uint8_t left,
-    uint8_t top,
-    uint8_t w,
-    uint8_t h,
-    DrawMode drawMode);
-
-void draw_icon_clip_flipped(
-    Canvas* const canvas,
-    const Icon* icon,
-    int16_t x,
-    int16_t y,
-    uint8_t left,
-    uint8_t top,
-    uint8_t w,
-    uint8_t h,
-    DrawMode drawMode);
-
-void draw_rounded_box(
-    Canvas* const canvas,
-    int16_t x,
-    int16_t y,
-    uint8_t w,
-    uint8_t h,
-    DrawMode drawMode);
-
-void draw_rounded_box_frame(
-    Canvas* const canvas,
-    int16_t x,
-    int16_t y,
-    uint8_t w,
-    uint8_t h,
-    DrawMode drawMode);
-
-void draw_rectangle(
-    Canvas* const canvas,
-    int16_t x,
-    int16_t y,
-    uint8_t w,
-    uint8_t h,
-    DrawMode drawMode);
-
-void invert_rectangle(Canvas* const canvas, int16_t x, int16_t y, uint8_t w, uint8_t h);
-
-void invert_shape(Canvas* const canvas, uint8_t* data, int16_t x, int16_t y, uint8_t w, uint8_t h);
-
-void draw_pixels(
-    Canvas* const canvas,
-    uint8_t* data,
-    int16_t x,
-    int16_t y,
-    uint8_t w,
-    uint8_t h,
-    DrawMode drawMode);
-
-bool read_pixel(Canvas* const canvas, int16_t x, int16_t y);
-
-void set_pixel(Canvas* const canvas, int16_t x, int16_t y, DrawMode draw_mode);
-
-void draw_line(
-    Canvas* const canvas,
-    int16_t x1,
-    int16_t y1,
-    int16_t x2,
-    int16_t y2,
-    DrawMode draw_mode);
-
-bool in_screen(int16_t x, int16_t y);
-
-void ui_cleanup();
-uint8_t* get_buffer(Canvas* const canvas);
-uint8_t* make_buffer();
-void clone_buffer(uint8_t* canvas, uint8_t* data);

+ 0 - 57
non_catalog_apps/solitaire/defines.h

@@ -1,57 +0,0 @@
-#pragma once
-#include <furi.h>
-#include <input/input.h>
-#include <gui/elements.h>
-#include <flipper_format/flipper_format.h>
-#include <flipper_format/flipper_format_i.h>
-#include "common/card.h"
-#include "common/queue.h"
-
-#define APP_NAME "Solitaire"
-
-typedef enum {
-    EventTypeTick,
-    EventTypeKey,
-} EventType;
-
-typedef struct {
-    EventType type;
-    InputEvent input;
-} AppEvent;
-
-typedef enum { GameStateGameOver, GameStateStart, GameStatePlay, GameStateAnimate } PlayState;
-
-typedef struct {
-    uint8_t* buffer;
-    Card card;
-    int8_t deck;
-    int indexes[4];
-    float x;
-    float y;
-    float vx;
-    float vy;
-    bool started;
-} CardAnimation;
-
-typedef struct {
-    Deck deck;
-    Hand bottom_columns[7];
-    Card top_cards[4];
-    bool dragging_deck;
-    uint8_t dragging_column;
-    Hand dragging_hand;
-
-    InputKey input;
-
-    bool started;
-    bool processing;
-    bool longPress;
-    PlayState state;
-    unsigned int last_tick;
-    uint8_t selectRow;
-    uint8_t selectColumn;
-    int8_t selected_card;
-    CardAnimation animation;
-    uint8_t* buffer;
-    FuriMutex* mutex;
-} GameState;

+ 0 - 575
non_catalog_apps/solitaire/solitaire.c

@@ -1,575 +0,0 @@
-#include <stdlib.h>
-#include <dolphin/dolphin.h>
-#include <furi.h>
-#include <gui/canvas_i.h>
-#include "defines.h"
-#include "common/ui.h"
-#include "solitaire_icons.h"
-#include <notification/notification.h>
-#include <notification/notification_messages.h>
-void init(GameState* game_state);
-const NotificationSequence sequence_fail = {
-    &message_vibro_on,
-    &message_note_c4,
-    &message_delay_10,
-    &message_vibro_off,
-    &message_sound_off,
-    &message_delay_10,
-
-    &message_vibro_on,
-    &message_note_a3,
-    &message_delay_10,
-    &message_vibro_off,
-    &message_sound_off,
-    NULL,
-};
-int8_t columns[7][3] = {
-    {1, 1, 25},
-    {19, 1, 25},
-    {37, 1, 25},
-    {55, 1, 25},
-    {73, 1, 25},
-    {91, 1, 25},
-    {109, 1, 25},
-};
-
-bool can_place_card(Card where, Card what) {
-    FURI_LOG_D(
-        APP_NAME,
-        "TESTING pip %i, letter %i with pip %i, letter %i",
-        where.pip,
-        where.character,
-        what.pip,
-        what.character);
-    bool a_black = where.pip == 0 || where.pip == 3;
-    bool b_black = what.pip == 0 || what.pip == 3;
-    if(a_black == b_black) return false;
-
-    int8_t a_letter = (int8_t)where.character;
-    int8_t b_letter = (int8_t)what.character;
-    if(a_letter == 12) a_letter = -1;
-    if(b_letter == 12) b_letter = -1;
-
-    return (a_letter - 1) == b_letter;
-}
-
-static void draw_scene(Canvas* const canvas, const GameState* game_state) {
-    int deckIndex = game_state->deck.index;
-    if(game_state->dragging_deck) deckIndex--;
-
-    if((game_state->deck.index < (game_state->deck.card_count - 1) ||
-        game_state->deck.index == -1) &&
-       game_state->deck.card_count > 0) {
-        draw_card_back_at(columns[0][0], columns[0][1], canvas);
-        if(game_state->selectRow == 0 && game_state->selectColumn == 0) {
-            draw_rounded_box(
-                canvas,
-                columns[0][0] + 1,
-                columns[0][1] + 1,
-                CARD_WIDTH - 2,
-                CARD_HEIGHT - 2,
-                Inverse);
-        }
-    } else
-        draw_card_space(
-            columns[0][0],
-            columns[0][1],
-            game_state->selectRow == 0 && game_state->selectColumn == 0,
-            canvas);
-    //deck side
-    if(deckIndex >= 0) {
-        Card c = game_state->deck.cards[deckIndex];
-        draw_card_at_colored(
-            columns[1][0],
-            columns[1][1],
-            c.pip,
-            c.character,
-            game_state->selectRow == 0 && game_state->selectColumn == 1,
-            canvas);
-    } else
-        draw_card_space(
-            columns[1][0],
-            columns[1][1],
-            game_state->selectRow == 0 && game_state->selectColumn == 1,
-            canvas);
-
-    for(uint8_t i = 0; i < 4; i++) {
-        Card current = game_state->top_cards[i];
-        bool selected = game_state->selectRow == 0 && game_state->selectColumn == (i + 3);
-        if(current.disabled) {
-            draw_card_space(columns[i + 3][0], columns[i + 3][1], selected, canvas);
-        } else {
-            draw_card_at(
-                columns[i + 3][0], columns[i + 3][1], current.pip, current.character, canvas);
-            if(selected) {
-                draw_rounded_box(
-                    canvas, columns[i + 3][0], columns[i + 3][1], CARD_WIDTH, CARD_HEIGHT, Inverse);
-            }
-        }
-    }
-
-    for(uint8_t i = 0; i < 7; i++) {
-        bool selected = game_state->selectRow == 1 && game_state->selectColumn == i;
-        int8_t index = (game_state->bottom_columns[i].index - 1 - game_state->selected_card);
-        if(index < 0) index = 0;
-        draw_hand_column(
-            game_state->bottom_columns[i],
-            columns[i][0],
-            columns[i][2],
-            selected ? index : -1,
-            canvas);
-    }
-
-    int8_t pos[2] = {
-        columns[game_state->selectColumn][0],
-        columns[game_state->selectColumn][game_state->selectRow + 1]};
-
-    /*     draw_icon_clip(canvas, &I_card_graphics, pos[0] + CARD_HALF_WIDTH, pos[1] + CARD_HALF_HEIGHT, 30, 5, 5, 5,
-                        Filled);*/
-
-    if(game_state->dragging_hand.index > 0) {
-        draw_hand_column(
-            game_state->dragging_hand,
-            pos[0] + CARD_HALF_WIDTH + 3,
-            pos[1] + CARD_HALF_HEIGHT + 3,
-            -1,
-            canvas);
-    }
-}
-
-static void draw_animation(Canvas* const canvas, const GameState* game_state) {
-    if(!game_state->animation.started) {
-        draw_scene(canvas, game_state);
-    } else {
-        clone_buffer(game_state->animation.buffer, get_buffer(canvas));
-
-        draw_card_at(
-            (int8_t)game_state->animation.x,
-            (int8_t)game_state->animation.y,
-            game_state->animation.card.pip,
-            game_state->animation.card.character,
-            canvas);
-    }
-
-    clone_buffer(get_buffer(canvas), game_state->animation.buffer);
-}
-
-static void render_callback(Canvas* const canvas, void* ctx) {
-    furi_assert(ctx);
-    const GameState* game_state = ctx;
-    furi_mutex_acquire(game_state->mutex, FuriWaitForever);
-
-    switch(game_state->state) {
-    case GameStateAnimate:
-        draw_animation(canvas, game_state);
-        break;
-    case GameStateStart:
-        canvas_draw_icon(canvas, 0, 0, &I_solitaire_main);
-        break;
-    case GameStatePlay:
-        draw_scene(canvas, game_state);
-        break;
-    default:
-        break;
-    }
-
-    furi_mutex_release(game_state->mutex);
-}
-
-void remove_drag(GameState* game_state) {
-    if(game_state->dragging_deck) {
-        remove_from_deck(game_state->deck.index, &(game_state->deck));
-        game_state->dragging_deck = false;
-    } else if(game_state->dragging_column < 7) {
-        game_state->dragging_column = 8;
-    }
-    game_state->dragging_hand.index = 0;
-}
-
-bool handleInput(GameState* game_state) {
-    Hand currentHand = game_state->bottom_columns[game_state->selectColumn];
-    switch(game_state->input) {
-    case InputKeyUp:
-        if(game_state->selectRow > 0) {
-            int first = first_non_flipped_card(currentHand);
-            first = currentHand.index - first;
-            if((first - 1) > game_state->selected_card && game_state->dragging_hand.index == 0 &&
-               !game_state->longPress) {
-                game_state->selected_card++;
-            } else {
-                game_state->selectRow--;
-                game_state->selected_card = 0;
-            }
-        }
-        break;
-    case InputKeyDown:
-        if(game_state->selectRow < 1) {
-            game_state->selectRow++;
-            game_state->selected_card = 0;
-        } else {
-            if(game_state->selected_card > 0) {
-                if(game_state->longPress)
-                    game_state->selected_card = 0;
-                else
-                    game_state->selected_card--;
-            }
-        }
-        break;
-    case InputKeyRight:
-        if(game_state->selectColumn < 6) {
-            game_state->selectColumn++;
-            game_state->selected_card = 0;
-        }
-        break;
-    case InputKeyLeft:
-        if(game_state->selectColumn > 0) {
-            game_state->selectColumn--;
-            game_state->selected_card = 0;
-        }
-        break;
-    case InputKeyOk:
-        return true;
-        break;
-    default:
-        break;
-    }
-    if(game_state->selectRow == 0 && game_state->selectColumn == 2) {
-        if(game_state->input == InputKeyRight)
-            game_state->selectColumn++;
-        else
-            game_state->selectColumn--;
-    }
-    if(game_state->dragging_hand.index > 0) game_state->selected_card = 0;
-    return false;
-}
-
-bool place_on_top(Card* where, Card what) {
-    if(where->disabled && what.character == 12) {
-        where->disabled = what.disabled;
-        where->pip = what.pip;
-        where->character = what.character;
-        return true;
-    } else if(where->pip == what.pip) {
-        int8_t a_letter = (int8_t)where->character;
-        int8_t b_letter = (int8_t)what.character;
-        if(a_letter == 12) a_letter = -1;
-        if(b_letter == 12) b_letter = -1;
-
-        if(where->disabled && b_letter != -1) return false;
-
-        if((a_letter + 1) == b_letter) {
-            where->disabled = what.disabled;
-            where->pip = what.pip;
-            where->character = what.character;
-            return true;
-        }
-    }
-    return false;
-}
-
-void tick(GameState* game_state, NotificationApp* notification) {
-    game_state->last_tick = furi_get_tick();
-    uint8_t row = game_state->selectRow;
-    uint8_t column = game_state->selectColumn;
-    if(game_state->state != GameStatePlay && game_state->state != GameStateAnimate) return;
-    bool wasAction = false;
-    if(game_state->state == GameStatePlay) {
-        if(game_state->top_cards[0].character == 11 && game_state->top_cards[1].character == 11 &&
-           game_state->top_cards[2].character == 11 && game_state->top_cards[3].character == 11) {
-            dolphin_deed(DolphinDeedPluginGameWin);
-            game_state->state = GameStateAnimate;
-            return;
-        }
-    }
-    if(handleInput(game_state)) {
-        if(game_state->state == GameStatePlay) {
-            if(game_state->longPress && game_state->dragging_hand.index == 1) {
-                for(uint8_t i = 0; i < 4; i++) {
-                    if(place_on_top(
-                           &(game_state->top_cards[i]), game_state->dragging_hand.cards[0])) {
-                        remove_drag(game_state);
-                        wasAction = true;
-                        break;
-                    }
-                }
-            } else {
-                if(row == 0 && column == 0 && game_state->dragging_hand.index == 0) {
-                    FURI_LOG_D(APP_NAME, "Drawing card");
-                    game_state->deck.index++;
-                    wasAction = true;
-                    if(game_state->deck.index >= (game_state->deck.card_count))
-                        game_state->deck.index = -1;
-                }
-                //pick/place from deck
-                else if(row == 0 && column == 1) {
-                    //place
-                    if(game_state->dragging_deck) {
-                        wasAction = true;
-                        game_state->dragging_deck = false;
-                        game_state->dragging_hand.index = 0;
-                    }
-                    //pick
-                    else {
-                        if(game_state->dragging_hand.index == 0 && game_state->deck.index >= 0) {
-                            wasAction = true;
-                            game_state->dragging_deck = true;
-                            add_to_hand(
-                                &(game_state->dragging_hand),
-                                game_state->deck.cards[game_state->deck.index]);
-                        }
-                    }
-                }
-                //place on top row
-                else if(row == 0 && game_state->dragging_hand.index == 1) {
-                    column -= 3;
-                    Card currCard = game_state->dragging_hand.cards[0];
-                    wasAction = place_on_top(&(game_state->top_cards[column]), currCard);
-                    if(wasAction) remove_drag(game_state);
-                }
-                //pick/place from bottom
-                else if(row == 1) {
-                    Hand* curr_hand = &(game_state->bottom_columns[column]);
-                    //pick up
-                    if(game_state->dragging_hand.index == 0) {
-                        Card curr_card = curr_hand->cards[curr_hand->index - 1];
-                        if(curr_card.flipped) {
-                            curr_hand->cards[curr_hand->index - 1].flipped = false;
-                            wasAction = true;
-                        } else {
-                            if(curr_hand->index > 0) {
-                                extract_hand_region(
-                                    curr_hand,
-                                    &(game_state->dragging_hand),
-                                    curr_hand->index - game_state->selected_card - 1);
-                                game_state->selected_card = 0;
-                                game_state->dragging_column = column;
-                                wasAction = true;
-                            }
-                        }
-                    }
-                    //place
-                    else {
-                        Card first = game_state->dragging_hand.cards[0];
-                        if(game_state->dragging_column == column ||
-                           (curr_hand->index == 0 && first.character == 11) ||
-                           can_place_card(curr_hand->cards[curr_hand->index - 1], first)) {
-                            add_hand_region(curr_hand, &(game_state->dragging_hand));
-                            remove_drag(game_state);
-                            wasAction = true;
-                        }
-                    }
-                }
-            }
-
-            if(!wasAction) {
-                notification_message(notification, &sequence_fail);
-            }
-        }
-    }
-    if(game_state->state == GameStateAnimate) {
-        if(game_state->animation.started && !game_state->longPress &&
-           game_state->input == InputKeyOk) {
-            init(game_state);
-            game_state->state = GameStateStart;
-        }
-
-        game_state->animation.started = true;
-        if(game_state->animation.x < -20 || game_state->animation.x > 128) {
-            game_state->animation.deck++;
-            if(game_state->animation.deck > 3) game_state->animation.deck = 0;
-            int8_t cardIndex = 11 - game_state->animation.indexes[game_state->animation.deck];
-
-            if(game_state->animation.indexes[0] == 13 && game_state->animation.indexes[1] == 13 &&
-               game_state->animation.indexes[2] == 13 && game_state->animation.indexes[3] == 13) {
-                init(game_state);
-                game_state->state = GameStateStart;
-                return;
-            }
-
-            if(cardIndex == -1) cardIndex = 12;
-            game_state->animation.card = (Card){
-                game_state->top_cards[game_state->animation.deck].pip, cardIndex, false, false};
-            game_state->animation.indexes[game_state->animation.deck]++;
-            game_state->animation.vx = -(rand() % 3 + 1) * (rand() % 2 == 1 ? 1 : -1);
-            game_state->animation.vy = (rand() % 3 + 1);
-            game_state->animation.x = columns[game_state->animation.deck + 3][0];
-            game_state->animation.y = columns[game_state->animation.deck + 3][1];
-        }
-        game_state->animation.x += game_state->animation.vx;
-        game_state->animation.y -= game_state->animation.vy;
-        game_state->animation.vy -= 1;
-        if(game_state->animation.vy < -10) game_state->animation.vy = -10;
-
-        if(game_state->animation.y > 41) {
-            game_state->animation.y = 41;
-            game_state->animation.vy = -(game_state->animation.vy * 0.7f);
-        }
-    }
-}
-
-void init(GameState* game_state) {
-    game_state->selectColumn = 0;
-    game_state->selected_card = 0;
-    game_state->selectRow = 0;
-    generate_deck(&(game_state->deck), 1);
-    shuffle_deck(&(game_state->deck));
-    game_state->dragging_deck = false;
-    game_state->animation.started = false;
-    game_state->animation.deck = -1;
-    game_state->animation.x = -21;
-    game_state->state = GameStatePlay;
-    game_state->dragging_column = 8;
-
-    for(uint8_t i = 0; i < 7; i++) {
-        free_hand(&(game_state->bottom_columns[i]));
-        init_hand(&(game_state->bottom_columns[i]), 21);
-        game_state->bottom_columns[i].index = 0;
-        for(uint8_t j = 0; j <= i; j++) {
-            Card cur = remove_from_deck(0, &(game_state->deck));
-            cur.flipped = i != j;
-            add_to_hand(&(game_state->bottom_columns[i]), cur);
-        }
-    }
-
-    for(uint8_t i = 0; i < 4; i++) {
-        game_state->animation.indexes[i] = 0;
-        game_state->top_cards[i] = (Card){0, 0, true, false};
-    }
-    game_state->deck.index = -1;
-}
-
-void init_start(GameState* game_state) {
-    game_state->input = InputKeyMAX;
-    for(uint8_t i = 0; i < 7; i++) init_hand(&(game_state->bottom_columns[i]), 21);
-
-    init_hand(&(game_state->dragging_hand), 13);
-    game_state->animation.buffer = make_buffer();
-}
-
-static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
-    furi_assert(event_queue);
-    AppEvent event = {.type = EventTypeKey, .input = *input_event};
-    furi_message_queue_put(event_queue, &event, FuriWaitForever);
-}
-
-static void update_timer_callback(FuriMessageQueue* event_queue) {
-    furi_assert(event_queue);
-    AppEvent event = {.type = EventTypeTick};
-    furi_message_queue_put(event_queue, &event, 0);
-}
-
-int32_t solitaire_app(void* p) {
-    UNUSED(p);
-    int32_t return_code = 0;
-    FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(AppEvent));
-    GameState* game_state = malloc(sizeof(GameState));
-    init_start(game_state);
-    set_card_graphics(&I_card_graphics);
-
-    game_state->state = GameStateStart;
-
-    game_state->processing = true;
-    game_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
-    if(!game_state->mutex) {
-        FURI_LOG_E(APP_NAME, "cannot create mutex\r\n");
-        return_code = 255;
-        goto free_and_exit;
-    }
-    NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
-
-    notification_message_block(notification, &sequence_display_backlight_enforce_on);
-
-    ViewPort* view_port = view_port_alloc();
-    view_port_draw_callback_set(view_port, render_callback, game_state);
-    view_port_input_callback_set(view_port, input_callback, event_queue);
-
-    FuriTimer* timer = furi_timer_alloc(update_timer_callback, FuriTimerTypePeriodic, event_queue);
-    furi_timer_start(timer, furi_kernel_get_tick_frequency() / 30);
-
-    Gui* gui = furi_record_open(RECORD_GUI);
-    gui_add_view_port(gui, view_port, GuiLayerFullscreen);
-
-    AppEvent event;
-
-    // Call Dolphin deed on game start
-    dolphin_deed(DolphinDeedPluginGameStart);
-
-    for(bool processing = true; processing;) {
-        FuriStatus event_status = furi_message_queue_get(event_queue, &event, 150);
-        furi_mutex_acquire(game_state->mutex, FuriWaitForever);
-        bool hadChange = false;
-        if(event_status == FuriStatusOk) {
-            if(event.type == EventTypeKey) {
-                if(event.input.type == InputTypeLong) {
-                    game_state->longPress = true;
-                    switch(event.input.key) {
-                    case InputKeyUp:
-                    case InputKeyDown:
-                    case InputKeyRight:
-                    case InputKeyLeft:
-                    case InputKeyOk:
-                        game_state->input = event.input.key;
-                        break;
-                    case InputKeyBack:
-                        processing = false;
-                        return_code = 1;
-                    default:
-                        break;
-                    }
-                } else if(event.input.type == InputTypePress) {
-                    game_state->longPress = false;
-                    switch(event.input.key) {
-                    case InputKeyUp:
-                    case InputKeyDown:
-                    case InputKeyRight:
-                    case InputKeyLeft:
-                    case InputKeyOk:
-                        if(event.input.key == InputKeyOk && game_state->state == GameStateStart) {
-                            game_state->state = GameStatePlay;
-                            init(game_state);
-                        } else {
-                            hadChange = true;
-                            game_state->input = event.input.key;
-                        }
-                        break;
-                    case InputKeyBack:
-                        init(game_state);
-                        processing = false;
-                        return_code = 1;
-                        break;
-                    default:
-                        break;
-                    }
-                }
-            } else if(event.type == EventTypeTick) {
-                tick(game_state, notification);
-                processing = game_state->processing;
-                game_state->input = InputKeyMAX;
-            }
-        } else {
-            //FURI_LOG_W(APP_NAME, "osMessageQueue: event timeout");
-            // event timeout
-        }
-        if(hadChange || game_state->state == GameStateAnimate) view_port_update(view_port);
-        furi_mutex_release(game_state->mutex);
-    }
-
-    notification_message_block(notification, &sequence_display_backlight_enforce_auto);
-    furi_timer_free(timer);
-    view_port_enabled_set(view_port, false);
-    gui_remove_view_port(gui, view_port);
-    furi_record_close(RECORD_GUI);
-    furi_record_close(RECORD_NOTIFICATION);
-    view_port_free(view_port);
-    furi_mutex_free(game_state->mutex);
-
-free_and_exit:
-    free(game_state->animation.buffer);
-    ui_cleanup();
-    for(uint8_t i = 0; i < 7; i++) free_hand(&(game_state->bottom_columns[i]));
-
-    free(game_state->deck.cards);
-    free(game_state);
-    furi_message_queue_free(event_queue);
-    return return_code;
-}

BIN
non_catalog_apps/solitaire/solitaire_10px.png


+ 4 - 4
non_catalog_apps/wii_ec_anal/wii_anal.c

@@ -385,7 +385,7 @@ int32_t wii_ec_anal(void) {
     // ==================== Main event loop ====================
 
     if(state->run) do {
-            bool redraw = false;
+            //bool redraw = false;
             FuriStatus status = FuriStatusErrorTimeout;
 
             // Wait for a message
@@ -449,13 +449,13 @@ int32_t wii_ec_anal(void) {
 
             //---------------------------------------------
             case EVID_WIIEC: // WiiMote Perhipheral
-                if(evWiiEC(&msg, state)) redraw = true;
+                evWiiEC(&msg, state); //) redraw = true;
                 break;
 
             //---------------------------------------------
             case EVID_KEY: // Key events
                 patBacklight(state);
-                if(evKey(&msg, state)) redraw = true;
+                evKey(&msg, state); //) redraw = true;
                 break;
 
             //---------------------------------------------
@@ -469,7 +469,7 @@ int32_t wii_ec_anal(void) {
             }
 
             // *** Update the GUI screen via the viewport ***
-            if(redraw) view_port_update(vpp);
+            view_port_update(vpp);
 
             // *** Try to release the plugin state variables ***
             furi_mutex_release(state->mutex);