diff --git a/applications/ReadMe.md b/applications/ReadMe.md index 91ef02bb..de465832 100644 --- a/applications/ReadMe.md +++ b/applications/ReadMe.md @@ -33,9 +33,6 @@ Applications for main Flipper menu. - `nfc` - NFC application, HF rfid, EMV and etc - `subghz` - SubGhz application, 433 fobs and etc - `u2f` - U2F Application -- `clock` - Clock application -- `music_player` - Music player app (demo) -- `snake_game` - Snake game application ## services diff --git a/applications/main/application.fam b/applications/main/application.fam index e3ceac34..0a90ee22 100644 --- a/applications/main/application.fam +++ b/applications/main/application.fam @@ -11,9 +11,6 @@ App( "subghz", "bad_usb", "u2f", - "clock", - "music_player", - "snake_game", "archive", "main_apps_on_start", ], diff --git a/applications/main/clock/application.fam b/applications/main/clock/application.fam deleted file mode 100644 index a6a2eff3..00000000 --- a/applications/main/clock/application.fam +++ /dev/null @@ -1,10 +0,0 @@ -App( - appid="clock", - name="Clock", - apptype=FlipperAppType.EXTERNAL, - entry_point="clock_app", - requires=["gui"], - stack_size=2 * 1024, - fap_icon="clock.png", - fap_category="Tools", -) diff --git a/applications/main/clock/clock.png b/applications/main/clock/clock.png deleted file mode 100644 index 0d96df10..00000000 Binary files a/applications/main/clock/clock.png and /dev/null differ diff --git a/applications/main/clock/clock_app.c b/applications/main/clock/clock_app.c deleted file mode 100644 index c938125b..00000000 --- a/applications/main/clock/clock_app.c +++ /dev/null @@ -1,136 +0,0 @@ -#include -#include - -#include -#include - -typedef enum { - ClockEventTypeTick, - ClockEventTypeKey, -} ClockEventType; - -typedef struct { - ClockEventType type; - InputEvent input; -} ClockEvent; - -typedef struct { - FuriString* buffer; - FuriHalRtcDateTime datetime; - LocaleTimeFormat timeformat; - LocaleDateFormat dateformat; -} ClockData; - -typedef struct { - FuriMutex* mutex; - FuriMessageQueue* queue; - ClockData* data; -} Clock; - -static void clock_input_callback(InputEvent* input_event, FuriMessageQueue* queue) { - furi_assert(queue); - ClockEvent event = {.type = ClockEventTypeKey, .input = *input_event}; - furi_message_queue_put(queue, &event, FuriWaitForever); -} - -static void clock_render_callback(Canvas* canvas, void* ctx) { - Clock* clock = ctx; - if(furi_mutex_acquire(clock->mutex, 200) != FuriStatusOk) { - return; - } - - ClockData* data = clock->data; - - canvas_set_font(canvas, FontBigNumbers); - locale_format_time(data->buffer, &data->datetime, data->timeformat, true); - canvas_draw_str_aligned( - canvas, 64, 28, AlignCenter, AlignCenter, furi_string_get_cstr(data->buffer)); - - // Special case to cover missing glyphs in FontBigNumbers - if(data->timeformat == LocaleTimeFormat12h) { - size_t time_width = canvas_string_width(canvas, furi_string_get_cstr(data->buffer)); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned( - canvas, - 64 + (time_width / 2) - 10, - 31, - AlignLeft, - AlignCenter, - (data->datetime.hour > 11) ? "PM" : "AM"); - } - - canvas_set_font(canvas, FontSecondary); - locale_format_date(data->buffer, &data->datetime, data->dateformat, "/"); - canvas_draw_str_aligned( - canvas, 64, 42, AlignCenter, AlignTop, furi_string_get_cstr(data->buffer)); - - furi_mutex_release(clock->mutex); -} - -static void clock_tick(void* ctx) { - furi_assert(ctx); - FuriMessageQueue* queue = ctx; - ClockEvent event = {.type = ClockEventTypeTick}; - // It's OK to loose this event if system overloaded - furi_message_queue_put(queue, &event, 0); -} - -int32_t clock_app(void* p) { - UNUSED(p); - Clock* clock = malloc(sizeof(Clock)); - clock->data = malloc(sizeof(ClockData)); - clock->data->buffer = furi_string_alloc(); - - clock->queue = furi_message_queue_alloc(8, sizeof(ClockEvent)); - clock->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - - furi_hal_rtc_get_datetime(&clock->data->datetime); - clock->data->timeformat = locale_get_time_format(); - clock->data->dateformat = locale_get_date_format(); - - // Set ViewPort callbacks - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, clock_render_callback, clock); - view_port_input_callback_set(view_port, clock_input_callback, clock->queue); - - FuriTimer* timer = furi_timer_alloc(clock_tick, FuriTimerTypePeriodic, clock->queue); - - // Open GUI and register view_port - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - furi_timer_start(timer, 100); - - // Main loop - ClockEvent event; - for(bool processing = true; processing;) { - furi_check(furi_message_queue_get(clock->queue, &event, FuriWaitForever) == FuriStatusOk); - furi_mutex_acquire(clock->mutex, FuriWaitForever); - if(event.type == ClockEventTypeKey) { - if(event.input.type == InputTypeShort && event.input.key == InputKeyBack) { - processing = false; - } - } else if(event.type == ClockEventTypeTick) { - furi_hal_rtc_get_datetime(&clock->data->datetime); - } - - furi_mutex_release(clock->mutex); - view_port_update(view_port); - } - - furi_timer_free(timer); - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - view_port_free(view_port); - furi_record_close(RECORD_GUI); - - furi_message_queue_free(clock->queue); - furi_mutex_free(clock->mutex); - - furi_string_free(clock->data->buffer); - - free(clock->data); - free(clock); - - return 0; -} diff --git a/applications/main/music_player/application.fam b/applications/main/music_player/application.fam deleted file mode 100644 index c9cd5e44..00000000 --- a/applications/main/music_player/application.fam +++ /dev/null @@ -1,16 +0,0 @@ -App( - appid="music_player", - name="Music Player", - apptype=FlipperAppType.EXTERNAL, - entry_point="music_player_app", - requires=[ - "gui", - "dialogs", - ], - stack_size=2 * 1024, - order=20, - fap_icon="icons/music_10px.png", - fap_category="Media", - fap_icon_assets="icons", - fap_libs=["music_worker"], -) diff --git a/applications/main/music_player/icons/music_10px.png b/applications/main/music_player/icons/music_10px.png deleted file mode 100644 index d41eb0db..00000000 Binary files a/applications/main/music_player/icons/music_10px.png and /dev/null differ diff --git a/applications/main/music_player/music_player.c b/applications/main/music_player/music_player.c deleted file mode 100644 index 8b0b758c..00000000 --- a/applications/main/music_player/music_player.c +++ /dev/null @@ -1,372 +0,0 @@ -#include - -#include -#include - -#include -#include -#include -#include - -#define TAG "MusicPlayer" - -#define MUSIC_PLAYER_APP_EXTENSION "*" - -#define MUSIC_PLAYER_SEMITONE_HISTORY_SIZE 4 - -typedef struct { - uint8_t semitone_history[MUSIC_PLAYER_SEMITONE_HISTORY_SIZE]; - uint8_t duration_history[MUSIC_PLAYER_SEMITONE_HISTORY_SIZE]; - - uint8_t volume; - uint8_t semitone; - uint8_t dots; - uint8_t duration; - float position; -} MusicPlayerModel; - -typedef struct { - MusicPlayerModel* model; - FuriMutex** model_mutex; - - FuriMessageQueue* input_queue; - - ViewPort* view_port; - Gui* gui; - - MusicWorker* worker; -} MusicPlayer; - -static const float MUSIC_PLAYER_VOLUMES[] = {0, .25, .5, .75, 1}; - -static const char* semitone_to_note(int8_t semitone) { - switch(semitone) { - case 0: - return "C"; - case 1: - return "C#"; - case 2: - return "D"; - case 3: - return "D#"; - case 4: - return "E"; - case 5: - return "F"; - case 6: - return "F#"; - case 7: - return "G"; - case 8: - return "G#"; - case 9: - return "A"; - case 10: - return "A#"; - case 11: - return "B"; - default: - return "--"; - } -} - -static bool is_white_note(uint8_t semitone, uint8_t id) { - switch(semitone) { - case 0: - if(id == 0) return true; - break; - case 2: - if(id == 1) return true; - break; - case 4: - if(id == 2) return true; - break; - case 5: - if(id == 3) return true; - break; - case 7: - if(id == 4) return true; - break; - case 9: - if(id == 5) return true; - break; - case 11: - if(id == 6) return true; - break; - default: - break; - } - - return false; -} - -static bool is_black_note(uint8_t semitone, uint8_t id) { - switch(semitone) { - case 1: - if(id == 0) return true; - break; - case 3: - if(id == 1) return true; - break; - case 6: - if(id == 3) return true; - break; - case 8: - if(id == 4) return true; - break; - case 10: - if(id == 5) return true; - break; - default: - break; - } - - return false; -} - -static void render_callback(Canvas* canvas, void* ctx) { - MusicPlayer* music_player = ctx; - furi_check(furi_mutex_acquire(music_player->model_mutex, FuriWaitForever) == FuriStatusOk); - - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 0, 12, "MusicPlayer"); - - uint8_t x_pos = 0; - uint8_t y_pos = 24; - const uint8_t white_w = 10; - const uint8_t white_h = 40; - - const int8_t black_x = 6; - const int8_t black_y = -5; - const uint8_t black_w = 8; - const uint8_t black_h = 32; - - // white keys - for(size_t i = 0; i < 7; i++) { - if(is_white_note(music_player->model->semitone, i)) { - canvas_draw_box(canvas, x_pos + white_w * i, y_pos, white_w + 1, white_h); - } else { - canvas_draw_frame(canvas, x_pos + white_w * i, y_pos, white_w + 1, white_h); - } - } - - // black keys - for(size_t i = 0; i < 7; i++) { - if(i != 2 && i != 6) { - canvas_set_color(canvas, ColorWhite); - canvas_draw_box( - canvas, x_pos + white_w * i + black_x, y_pos + black_y, black_w + 1, black_h); - canvas_set_color(canvas, ColorBlack); - if(is_black_note(music_player->model->semitone, i)) { - canvas_draw_box( - canvas, x_pos + white_w * i + black_x, y_pos + black_y, black_w + 1, black_h); - } else { - canvas_draw_frame( - canvas, x_pos + white_w * i + black_x, y_pos + black_y, black_w + 1, black_h); - } - } - } - - // volume view_port - x_pos = 124; - y_pos = 0; - const uint8_t volume_h = - (64 / (COUNT_OF(MUSIC_PLAYER_VOLUMES) - 1)) * music_player->model->volume; - canvas_draw_frame(canvas, x_pos, y_pos, 4, 64); - canvas_draw_box(canvas, x_pos, y_pos + (64 - volume_h), 4, volume_h); - - // note stack view_port - x_pos = 73; - y_pos = 0; //-V1048 - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontPrimary); - canvas_draw_frame(canvas, x_pos, y_pos, 49, 64); - canvas_draw_line(canvas, x_pos + 28, 0, x_pos + 28, 64); - - char duration_text[16]; - for(uint8_t i = 0; i < MUSIC_PLAYER_SEMITONE_HISTORY_SIZE; i++) { - if(music_player->model->duration_history[i] == 0xFF) { - snprintf(duration_text, 15, "--"); - } else { - snprintf(duration_text, 15, "%d", music_player->model->duration_history[i]); - } - - if(i == 0) { - canvas_draw_box(canvas, x_pos, y_pos + 48, 49, 16); - canvas_set_color(canvas, ColorWhite); - } else { - canvas_set_color(canvas, ColorBlack); - } - canvas_draw_str( - canvas, - x_pos + 4, - 64 - 16 * i - 3, - semitone_to_note(music_player->model->semitone_history[i])); - canvas_draw_str(canvas, x_pos + 31, 64 - 16 * i - 3, duration_text); - canvas_draw_line(canvas, x_pos, 64 - 16 * i, x_pos + 48, 64 - 16 * i); - } - - furi_mutex_release(music_player->model_mutex); -} - -static void input_callback(InputEvent* input_event, void* ctx) { - MusicPlayer* music_player = ctx; - if(input_event->type == InputTypeShort) { - furi_message_queue_put(music_player->input_queue, input_event, 0); - } -} - -static void music_worker_callback( - uint8_t semitone, - uint8_t dots, - uint8_t duration, - float position, - void* context) { - MusicPlayer* music_player = context; - furi_check(furi_mutex_acquire(music_player->model_mutex, FuriWaitForever) == FuriStatusOk); - - for(size_t i = 0; i < MUSIC_PLAYER_SEMITONE_HISTORY_SIZE - 1; i++) { - size_t r = MUSIC_PLAYER_SEMITONE_HISTORY_SIZE - 1 - i; - music_player->model->duration_history[r] = music_player->model->duration_history[r - 1]; - music_player->model->semitone_history[r] = music_player->model->semitone_history[r - 1]; - } - - semitone = (semitone == 0xFF) ? 0xFF : semitone % 12; - - music_player->model->semitone = semitone; - music_player->model->dots = dots; - music_player->model->duration = duration; - music_player->model->position = position; - - music_player->model->semitone_history[0] = semitone; - music_player->model->duration_history[0] = duration; - - furi_mutex_release(music_player->model_mutex); - view_port_update(music_player->view_port); -} - -void music_player_clear(MusicPlayer* instance) { - memset(instance->model->duration_history, 0xff, MUSIC_PLAYER_SEMITONE_HISTORY_SIZE); - memset(instance->model->semitone_history, 0xff, MUSIC_PLAYER_SEMITONE_HISTORY_SIZE); - music_worker_clear(instance->worker); -} - -MusicPlayer* music_player_alloc() { - MusicPlayer* instance = malloc(sizeof(MusicPlayer)); - - instance->model = malloc(sizeof(MusicPlayerModel)); - instance->model->volume = 3; - - instance->model_mutex = furi_mutex_alloc(FuriMutexTypeNormal); - - instance->input_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); - - instance->worker = music_worker_alloc(); - music_worker_set_volume(instance->worker, MUSIC_PLAYER_VOLUMES[instance->model->volume]); - music_worker_set_callback(instance->worker, music_worker_callback, instance); - - music_player_clear(instance); - - instance->view_port = view_port_alloc(); - view_port_draw_callback_set(instance->view_port, render_callback, instance); - view_port_input_callback_set(instance->view_port, input_callback, instance); - - // Open GUI and register view_port - instance->gui = furi_record_open(RECORD_GUI); - gui_add_view_port(instance->gui, instance->view_port, GuiLayerFullscreen); - - return instance; -} - -void music_player_free(MusicPlayer* instance) { - gui_remove_view_port(instance->gui, instance->view_port); - furi_record_close(RECORD_GUI); - view_port_free(instance->view_port); - - music_worker_free(instance->worker); - - furi_message_queue_free(instance->input_queue); - - furi_mutex_free(instance->model_mutex); - - free(instance->model); - free(instance); -} - -int32_t music_player_app(void* p) { - MusicPlayer* music_player = music_player_alloc(); - - FuriString* file_path; - file_path = furi_string_alloc(); - - do { - if(p && strlen(p)) { - furi_string_set(file_path, (const char*)p); - } else { - Storage* storage = furi_record_open(RECORD_STORAGE); - storage_common_migrate( - storage, EXT_PATH("music_player"), STORAGE_APP_DATA_PATH_PREFIX); - furi_record_close(RECORD_STORAGE); - - furi_string_set(file_path, STORAGE_APP_DATA_PATH_PREFIX); - - DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options( - &browser_options, MUSIC_PLAYER_APP_EXTENSION, &I_music_10px); - browser_options.hide_ext = false; - browser_options.base_path = STORAGE_APP_DATA_PATH_PREFIX; - - DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); - bool res = dialog_file_browser_show(dialogs, file_path, file_path, &browser_options); - - furi_record_close(RECORD_DIALOGS); - - if(!res) { - FURI_LOG_E(TAG, "No file selected"); - break; - } - } - - if(!music_worker_load(music_player->worker, furi_string_get_cstr(file_path))) { - FURI_LOG_E(TAG, "Unable to load file"); - break; - } - - music_worker_start(music_player->worker); - - InputEvent input; - while(furi_message_queue_get(music_player->input_queue, &input, FuriWaitForever) == - FuriStatusOk) { - furi_check( - furi_mutex_acquire(music_player->model_mutex, FuriWaitForever) == FuriStatusOk); - - if(input.key == InputKeyBack) { - furi_mutex_release(music_player->model_mutex); - break; - } else if(input.key == InputKeyUp) { - if(music_player->model->volume < COUNT_OF(MUSIC_PLAYER_VOLUMES) - 1) - music_player->model->volume++; - music_worker_set_volume( - music_player->worker, MUSIC_PLAYER_VOLUMES[music_player->model->volume]); - } else if(input.key == InputKeyDown) { - if(music_player->model->volume > 0) music_player->model->volume--; - music_worker_set_volume( - music_player->worker, MUSIC_PLAYER_VOLUMES[music_player->model->volume]); - } - - furi_mutex_release(music_player->model_mutex); - view_port_update(music_player->view_port); - } - - music_worker_stop(music_player->worker); - if(p && strlen(p)) break; // Exit instead of going to browser if launched with arg - music_player_clear(music_player); - } while(1); - - furi_string_free(file_path); - music_player_free(music_player); - - return 0; -} diff --git a/applications/main/snake_game/application.fam b/applications/main/snake_game/application.fam deleted file mode 100644 index c736a4dd..00000000 --- a/applications/main/snake_game/application.fam +++ /dev/null @@ -1,11 +0,0 @@ -App( - appid="snake_game", - name="Snake Game", - apptype=FlipperAppType.EXTERNAL, - entry_point="snake_game_app", - requires=["gui"], - stack_size=1 * 1024, - order=30, - fap_icon="snake_10px.png", - fap_category="Games", -) diff --git a/applications/main/snake_game/snake_10px.png b/applications/main/snake_game/snake_10px.png deleted file mode 100644 index 52d9fa7e..00000000 Binary files a/applications/main/snake_game/snake_10px.png and /dev/null differ diff --git a/applications/main/snake_game/snake_game.c b/applications/main/snake_game/snake_game.c deleted file mode 100644 index 6852cb21..00000000 --- a/applications/main/snake_game/snake_game.c +++ /dev/null @@ -1,434 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -typedef struct { - // +-----x - // | - // | - // y - uint8_t x; - uint8_t y; -} Point; - -typedef enum { - GameStateLife, - - // https://melmagazine.com/en-us/story/snake-nokia-6110-oral-history-taneli-armanto - // Armanto: While testing the early versions of the game, I noticed it was hard - // to control the snake upon getting close to and edge but not crashing — especially - // in the highest speed levels. I wanted the highest level to be as fast as I could - // possibly make the device "run," but on the other hand, I wanted to be friendly - // and help the player manage that level. Otherwise it might not be fun to play. So - // I implemented a little delay. A few milliseconds of extra time right before - // the player crashes, during which she can still change the directions. And if - // she does, the game continues. - GameStateLastChance, - - GameStateGameOver, -} GameState; - -// Note: do not change without purpose. Current values are used in smart -// orthogonality calculation in `snake_game_get_turn_snake`. -typedef enum { - DirectionUp, - DirectionRight, - DirectionDown, - DirectionLeft, -} Direction; - -#define MAX_SNAKE_LEN 253 - -typedef struct { - Point points[MAX_SNAKE_LEN]; - uint16_t len; - Direction currentMovement; - Direction nextMovement; // if backward of currentMovement, ignore - Point fruit; - GameState state; - FuriMutex* mutex; -} SnakeState; - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef struct { - EventType type; - InputEvent input; -} SnakeEvent; - -const NotificationSequence sequence_fail = { - &message_vibro_on, - - &message_note_ds4, - &message_delay_10, - &message_sound_off, - &message_delay_10, - - &message_note_ds4, - &message_delay_10, - &message_sound_off, - &message_delay_10, - - &message_note_ds4, - &message_delay_10, - &message_sound_off, - &message_delay_10, - - &message_vibro_off, - NULL, -}; - -const NotificationSequence sequence_eat = { - &message_note_c7, - &message_delay_50, - &message_sound_off, - NULL, -}; - -static void snake_game_render_callback(Canvas* const canvas, void* ctx) { - furi_assert(ctx); - const SnakeState* snake_state = ctx; - - furi_mutex_acquire(snake_state->mutex, FuriWaitForever); - - // Frame - canvas_draw_frame(canvas, 0, 0, 128, 64); - - // Fruit - Point f = snake_state->fruit; - f.x = f.x * 4 + 1; - f.y = f.y * 4 + 1; - canvas_draw_rframe(canvas, f.x, f.y, 6, 6, 2); - - // Snake - for(uint16_t i = 0; i < snake_state->len; i++) { - Point p = snake_state->points[i]; - p.x = p.x * 4 + 2; - p.y = p.y * 4 + 2; - canvas_draw_box(canvas, p.x, p.y, 4, 4); - } - - // Game Over banner - if(snake_state->state == GameStateGameOver) { - // Screen is 128x64 px - canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, 34, 20, 62, 24); - - canvas_set_color(canvas, ColorBlack); - canvas_draw_frame(canvas, 34, 20, 62, 24); - - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 37, 31, "Game Over"); - - canvas_set_font(canvas, FontSecondary); - char buffer[12]; - snprintf(buffer, sizeof(buffer), "Score: %u", snake_state->len - 7U); - canvas_draw_str_aligned(canvas, 64, 41, AlignCenter, AlignBottom, buffer); - } - - furi_mutex_release(snake_state->mutex); -} - -static void snake_game_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - SnakeEvent event = {.type = EventTypeKey, .input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -static void snake_game_update_timer_callback(FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - SnakeEvent event = {.type = EventTypeTick}; - furi_message_queue_put(event_queue, &event, 0); -} - -static void snake_game_init_game(SnakeState* const snake_state) { - Point p[] = {{8, 6}, {7, 6}, {6, 6}, {5, 6}, {4, 6}, {3, 6}, {2, 6}}; - memcpy(snake_state->points, p, sizeof(p)); //-V1086 - - snake_state->len = 7; - - snake_state->currentMovement = DirectionRight; - - snake_state->nextMovement = DirectionRight; - - Point f = {18, 6}; - snake_state->fruit = f; - - snake_state->state = GameStateLife; -} - -static Point snake_game_get_new_fruit(SnakeState const* const snake_state) { - // 1 bit for each point on the playing field where the snake can turn - // and where the fruit can appear - uint16_t buffer[8]; - memset(buffer, 0, sizeof(buffer)); - uint8_t empty = 8 * 16; - - for(uint16_t i = 0; i < snake_state->len; i++) { - Point p = snake_state->points[i]; - - if(p.x % 2 != 0 || p.y % 2 != 0) { - continue; - } - p.x /= 2; - p.y /= 2; - - buffer[p.y] |= 1 << p.x; - empty--; - } - // Bit set if snake use that playing field - - uint16_t newFruit = rand() % empty; - - // Skip random number of _empty_ fields - for(uint8_t y = 0; y < 8; y++) { - for(uint16_t x = 0, mask = 1; x < 16; x += 1, mask <<= 1) { - if((buffer[y] & mask) == 0) { - if(newFruit == 0) { - Point p = { - .x = x * 2, - .y = y * 2, - }; - return p; - } - newFruit--; - } - } - } - // We will never be here - Point p = {0, 0}; - return p; -} - -static bool snake_game_collision_with_frame(Point const next_step) { - // if x == 0 && currentMovement == left then x - 1 == 255 , - // so check only x > right border - return next_step.x > 30 || next_step.y > 14; -} - -static bool - snake_game_collision_with_tail(SnakeState const* const snake_state, Point const next_step) { - for(uint16_t i = 0; i < snake_state->len; i++) { - Point p = snake_state->points[i]; - if(p.x == next_step.x && p.y == next_step.y) { - return true; - } - } - - return false; -} - -static Direction snake_game_get_turn_snake(SnakeState const* const snake_state) { - // Sum of two `Direction` lies between 0 and 6, odd values indicate orthogonality. - bool is_orthogonal = (snake_state->currentMovement + snake_state->nextMovement) % 2 == 1; - return is_orthogonal ? snake_state->nextMovement : snake_state->currentMovement; -} - -static Point snake_game_get_next_step(SnakeState const* const snake_state) { - Point next_step = snake_state->points[0]; - switch(snake_state->currentMovement) { - // +-----x - // | - // | - // y - case DirectionUp: - next_step.y--; - break; - case DirectionRight: - next_step.x++; - break; - case DirectionDown: - next_step.y++; - break; - case DirectionLeft: - next_step.x--; - break; - } - return next_step; -} - -static void snake_game_move_snake(SnakeState* const snake_state, Point const next_step) { - memmove(snake_state->points + 1, snake_state->points, snake_state->len * sizeof(Point)); - snake_state->points[0] = next_step; -} - -static void - snake_game_process_game_step(SnakeState* const snake_state, NotificationApp* notification) { - if(snake_state->state == GameStateGameOver) { - return; - } - - bool can_turn = (snake_state->points[0].x % 2 == 0) && (snake_state->points[0].y % 2 == 0); - if(can_turn) { - snake_state->currentMovement = snake_game_get_turn_snake(snake_state); - } - - Point next_step = snake_game_get_next_step(snake_state); - - bool crush = snake_game_collision_with_frame(next_step); - if(crush) { - if(snake_state->state == GameStateLife) { - snake_state->state = GameStateLastChance; - return; - } else if(snake_state->state == GameStateLastChance) { - snake_state->state = GameStateGameOver; - notification_message_block(notification, &sequence_fail); - return; - } - } else { - if(snake_state->state == GameStateLastChance) { - snake_state->state = GameStateLife; - } - } - - crush = snake_game_collision_with_tail(snake_state, next_step); - if(crush) { - snake_state->state = GameStateGameOver; - notification_message_block(notification, &sequence_fail); - return; - } - - bool eatFruit = (next_step.x == snake_state->fruit.x) && (next_step.y == snake_state->fruit.y); - if(eatFruit) { - snake_state->len++; - if(snake_state->len >= MAX_SNAKE_LEN) { - snake_state->state = GameStateGameOver; - notification_message_block(notification, &sequence_fail); - return; - } - } - - snake_game_move_snake(snake_state, next_step); - - if(eatFruit) { - snake_state->fruit = snake_game_get_new_fruit(snake_state); - notification_message(notification, &sequence_eat); - } -} - -int32_t snake_game_app(void* p) { - UNUSED(p); - - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(SnakeEvent)); - - SnakeState* snake_state = malloc(sizeof(SnakeState)); - snake_game_init_game(snake_state); - - snake_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - - if(!snake_state->mutex) { - FURI_LOG_E("SnakeGame", "cannot create mutex\r\n"); - free(snake_state); - return 255; - } - - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, snake_game_render_callback, snake_state); - view_port_input_callback_set(view_port, snake_game_input_callback, event_queue); - - FuriTimer* timer = - furi_timer_alloc(snake_game_update_timer_callback, FuriTimerTypePeriodic, event_queue); - furi_timer_start(timer, furi_kernel_get_tick_frequency() / 4); - - // Open GUI and register view_port - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); - - notification_message_block(notification, &sequence_display_backlight_enforce_on); - - dolphin_deed(DolphinDeedPluginGameStart); - - SnakeEvent event; - for(bool processing = true; processing;) { - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); - - furi_mutex_acquire(snake_state->mutex, FuriWaitForever); - - if(event_status == FuriStatusOk) { - // press events - if(event.type == EventTypeKey) { - if(event.input.type == InputTypePress) { - switch(event.input.key) { - case InputKeyUp: - snake_state->nextMovement = DirectionUp; - break; - case InputKeyDown: - snake_state->nextMovement = DirectionDown; - break; - case InputKeyRight: - snake_state->nextMovement = DirectionRight; - break; - case InputKeyLeft: - snake_state->nextMovement = DirectionLeft; - break; - case InputKeyOk: - if(snake_state->state == GameStateGameOver) { - snake_game_init_game(snake_state); - } - break; - case InputKeyBack: - processing = false; - break; - default: - break; - } - } - } else if(event.type == EventTypeTick) { - snake_game_process_game_step(snake_state, notification); - } - } else { - // event timeout - } - - view_port_update(view_port); - furi_mutex_release(snake_state->mutex); - } - - // Return backlight to normal state - notification_message(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_message_queue_free(event_queue); - furi_mutex_free(snake_state->mutex); - free(snake_state); - - return 0; -} - -// Screen is 128x64 px -// (4 + 4) * 16 - 4 + 2 + 2border == 128 -// (4 + 4) * 8 - 4 + 2 + 2border == 64 -// Game field from point{x: 0, y: 0} to point{x: 30, y: 14}. -// The snake turns only in even cells - intersections. -// ┌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┐ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// └╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┘ diff --git a/assets/resources/apps_data/music_player/Marble_Machine.fmf b/assets/resources/apps_data/music_player/Marble_Machine.fmf deleted file mode 100644 index 7403c9a0..00000000 --- a/assets/resources/apps_data/music_player/Marble_Machine.fmf +++ /dev/null @@ -1,6 +0,0 @@ -Filetype: Flipper Music Format -Version: 0 -BPM: 130 -Duration: 8 -Octave: 5 -Notes: E6, P, E, B, 4P, E, A, G, A, E, B, P, G, A, D6, 4P, D, B, 4P, D, A, G, A, D, F#, P, G, A, D6, 4P, F#, B, 4P, F#, D6, C6, B, F#, A, P, G, F#, E, P, C, E, B, B4, C, D, D6, C6, B, F#, A, P, G, A, E6, 4P, E, B, 4P, E, A, G, A, E, B, P, G, A, D6, 4P, D, B, 4P, D, A, G, A, D, F#, P, G, A, D6, 4P, F#, B, 4P, F#, D6, C6, B, F#, A, P, G, F#, E, P, C, E, B, B4, C, D, D6, C6, B, F#, A, P, G, A, E6 diff --git a/assets/resources/apps_data/picopass/assets/iclass_elite_dict.txt b/assets/resources/apps_data/picopass/assets/iclass_elite_dict.txt deleted file mode 100644 index 908889ae..00000000 --- a/assets/resources/apps_data/picopass/assets/iclass_elite_dict.txt +++ /dev/null @@ -1,41 +0,0 @@ - -## From https://github.com/RfidResearchGroup/proxmark3/blob/master/client/dictionaries/iclass_default_keys.dic - -# key1/Kc from PicoPass 2k documentation -7665544332211000 -# SAGEM -0123456789ABCDEF -# PicoPass Default Exchange Key -5CBCF1DA45D5FB4F -# From HID multiclassSE reader -31ad7ebd2f282168 -# From pastebin: https://pastebin.com/uHqpjiuU -6EFD46EFCBB3C875 -E033CA419AEE43F9 - -# default picopass KD / Page 0 / Book 1 -FDCB5A52EA8F3090 -237FF9079863DF44 -5ADC25FB27181D32 -83B881F2936B2E49 -43644E61EE866BA5 -897034143D016080 -82D17B44C0122963 -4895CA7DE65E2025 -DADAD4C57BE271B7 -E41E9EDEF5719ABF -293D275EC3AF9C7F -C3C169251B8A70FB -F41DAF58B20C8B91 -28877A609EC0DD2B -66584C91EE80D5E5 -C1B74D7478053AE2 - -# default iCLASS RFIDeas -6B65797374726B72 - -# CTF key -5C100DF7042EAE64 - -# iCopy-X DRM key (iCE product) -2020666666668888 diff --git a/assets/resources/apps_data/picopass/assets/iclass_standard_dict.txt b/assets/resources/apps_data/picopass/assets/iclass_standard_dict.txt deleted file mode 100644 index 46808ef6..00000000 --- a/assets/resources/apps_data/picopass/assets/iclass_standard_dict.txt +++ /dev/null @@ -1,47 +0,0 @@ - -## From https://github.com/RfidResearchGroup/proxmark3/blob/master/client/dictionaries/iclass_default_keys.dic - -# AA1 -AEA684A6DAB23278 -# key1/Kc from PicoPass 2k documentation -7665544332211000 -# SAGEM -0123456789ABCDEF -# from loclass demo file. -5b7c62c491c11b39 -# Kd from PicoPass 2k documentation -F0E1D2C3B4A59687 -# PicoPass Default Exchange Key -5CBCF1DA45D5FB4F -# From HID multiclassSE reader -31ad7ebd2f282168 -# From pastebin: https://pastebin.com/uHqpjiuU -6EFD46EFCBB3C875 -E033CA419AEE43F9 - -# iCopy-x DRM keys -# iCL tags -2020666666668888 -# iCS tags reversed from the SOs -6666202066668888 - -# default picopass KD / Page 0 / Book 1 -FDCB5A52EA8F3090 -237FF9079863DF44 -5ADC25FB27181D32 -83B881F2936B2E49 -43644E61EE866BA5 -897034143D016080 -82D17B44C0122963 -4895CA7DE65E2025 -DADAD4C57BE271B7 -E41E9EDEF5719ABF -293D275EC3AF9C7F -C3C169251B8A70FB -F41DAF58B20C8B91 -28877A609EC0DD2B -66584C91EE80D5E5 -C1B74D7478053AE2 - -# default iCLASS RFIDeas -6B65797374726B72