diff --git a/applications/plugins/arkanoid/arkanoid_game.c b/applications/plugins/arkanoid/arkanoid_game.c index 0e96277f2..70b8da256 100644 --- a/applications/plugins/arkanoid/arkanoid_game.c +++ b/applications/plugins/arkanoid/arkanoid_game.c @@ -10,6 +10,7 @@ #define FLIPPER_LCD_WIDTH 128 #define FLIPPER_LCD_HEIGHT 64 +#define MAX_SPEED 3 typedef enum { EventTypeTick, EventTypeKey } EventType; @@ -51,6 +52,7 @@ typedef struct { unsigned int brickCount; //Amount of bricks hit int tick; //Tick counter bool gameStarted; // Did the game start? + int speed; // Ball speed } ArkanoidState; typedef struct { @@ -72,12 +74,18 @@ int rand_range(int min, int max) { void move_ball(Canvas* canvas, ArkanoidState* st) { st->tick++; + + int current_speed = abs(st->speed-1 - MAX_SPEED); + if (st->tick % current_speed != 0 && st->tick % (current_speed + 1) != 0) { + return; + } + if(st->ball_state.released) { //Move ball if(abs(st->ball_state.dx) == 2) { st->ball_state.xb += st->ball_state.dx / 2; // 2x speed is really 1.5 speed - if(st->tick % 2 == 0) st->ball_state.xb += st->ball_state.dx / 2; + if((st->tick / current_speed) % 2 == 0) st->ball_state.xb += st->ball_state.dx / 2; } else { st->ball_state.xb += st->ball_state.dx; } @@ -286,6 +294,7 @@ static void arkanoid_state_init(ArkanoidState* arkanoid_state) { arkanoid_state->ROWS = 4; arkanoid_state->ball_state.dx = -1; arkanoid_state->ball_state.dy = -1; + arkanoid_state->speed = 2; arkanoid_state->bounced = false; arkanoid_state->lives = 3; arkanoid_state->level = 1; @@ -414,8 +423,14 @@ int32_t arkanoid_game_app(void* p) { } break; case InputKeyUp: + if(arkanoid_state->speed < MAX_SPEED) { + arkanoid_state->speed++; + } break; case InputKeyDown: + if(arkanoid_state->speed > 1) { + arkanoid_state->speed--; + } break; case InputKeyOk: if(arkanoid_state->gameStarted == false) { diff --git a/applications/plugins/music_player/music_player.c b/applications/plugins/music_player/music_player.c index 6d3c4483e..192500c2e 100644 --- a/applications/plugins/music_player/music_player.c +++ b/applications/plugins/music_player/music_player.c @@ -248,12 +248,16 @@ static void music_player_worker_callback( 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_player_worker_clear(instance->worker); +} + MusicPlayer* music_player_alloc() { MusicPlayer* instance = malloc(sizeof(MusicPlayer)); instance->model = malloc(sizeof(MusicPlayerModel)); - memset(instance->model->duration_history, 0xff, MUSIC_PLAYER_SEMITONE_HISTORY_SIZE); - memset(instance->model->semitone_history, 0xff, MUSIC_PLAYER_SEMITONE_HISTORY_SIZE); instance->model->volume = 3; instance->model_mutex = furi_mutex_alloc(FuriMutexTypeNormal); @@ -265,6 +269,8 @@ MusicPlayer* music_player_alloc() { instance->worker, MUSIC_PLAYER_VOLUMES[instance->model->volume]); music_player_worker_set_callback(instance->worker, music_player_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); @@ -299,7 +305,7 @@ int32_t music_player_app(void* p) { do { if(p && strlen(p)) { - furi_string_cat(file_path, (const char*)p); + furi_string_set(file_path, (const char*)p); } else { furi_string_set(file_path, MUSIC_PLAYER_APP_PATH_FOLDER); @@ -350,7 +356,9 @@ int32_t music_player_app(void* p) { } music_player_worker_stop(music_player->worker); - } while(0); + 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); diff --git a/applications/plugins/music_player/music_player_worker.c b/applications/plugins/music_player/music_player_worker.c index 99f0ce1e5..3f1ac62f7 100644 --- a/applications/plugins/music_player/music_player_worker.c +++ b/applications/plugins/music_player/music_player_worker.c @@ -108,6 +108,10 @@ MusicPlayerWorker* music_player_worker_alloc() { return instance; } +void music_player_worker_clear(MusicPlayerWorker* instance) { + NoteBlockArray_reset(instance->notes); +} + void music_player_worker_free(MusicPlayerWorker* instance) { furi_assert(instance); furi_thread_free(instance->thread); @@ -129,6 +133,7 @@ static bool is_space(const char c) { static size_t extract_number(const char* string, uint32_t* number) { size_t ret = 0; + *number = 0; while(is_digit(*string)) { *number *= 10; *number += (*string - '0'); @@ -140,6 +145,7 @@ static size_t extract_number(const char* string, uint32_t* number) { static size_t extract_dots(const char* string, uint32_t* number) { size_t ret = 0; + *number = 0; while(*string == '.') { *number += 1; string++; diff --git a/applications/plugins/music_player/music_player_worker.h b/applications/plugins/music_player/music_player_worker.h index 9958a9273..acf824086 100644 --- a/applications/plugins/music_player/music_player_worker.h +++ b/applications/plugins/music_player/music_player_worker.h @@ -18,6 +18,8 @@ typedef struct MusicPlayerWorker MusicPlayerWorker; MusicPlayerWorker* music_player_worker_alloc(); +void music_player_worker_clear(MusicPlayerWorker* instance); + void music_player_worker_free(MusicPlayerWorker* instance); bool music_player_worker_load(MusicPlayerWorker* instance, const char* file_path); diff --git a/applications/services/gui/modules/file_browser.c b/applications/services/gui/modules/file_browser.c index f15b09f6b..762fe87d5 100644 --- a/applications/services/gui/modules/file_browser.c +++ b/applications/services/gui/modules/file_browser.c @@ -57,7 +57,6 @@ static void BrowserItem_t_set(BrowserItem_t* obj, const BrowserItem_t* src) { furi_string_set(obj->path, src->path); furi_string_set(obj->display_name, src->display_name); if(src->custom_icon_data) { - obj->custom_icon_data = malloc(CUSTOM_ICON_MAX_SIZE); memcpy(obj->custom_icon_data, src->custom_icon_data, CUSTOM_ICON_MAX_SIZE); } else { obj->custom_icon_data = NULL; @@ -379,6 +378,9 @@ static void }); furi_string_free(item.display_name); furi_string_free(item.path); + if(item.custom_icon_data) { + free(item.custom_icon_data); + } } else { with_view_model( browser->view, (FileBrowserModel * model) { diff --git a/lib/flipper_application/elf/elf_file.c b/lib/flipper_application/elf/elf_file.c index c70af067e..388f64d37 100644 --- a/lib/flipper_application/elf/elf_file.c +++ b/lib/flipper_application/elf/elf_file.c @@ -452,6 +452,10 @@ static bool elf_load_debug_link(ELFFile* elf, Elf32_Shdr* section_header) { section_header->sh_size; } +static bool str_prefix(const char* str, const char* prefix) { + return strncmp(prefix, str, strlen(prefix)) == 0; +} + static bool elf_load_section_data(ELFFile* elf, ELFSection* section, Elf32_Shdr* section_header) { if(section_header->sh_size == 0) { FURI_LOG_D(TAG, "No data for section"); @@ -485,6 +489,43 @@ static SectionType elf_preload_section( FlipperApplicationManifest* manifest) { const char* name = furi_string_get_cstr(name_string); +#ifdef ELF_DEBUG_LOG + // log section name, type and flags + FuriString* flags_string = furi_string_alloc(); + if(section_header->sh_flags & SHF_WRITE) furi_string_cat(flags_string, "W"); + if(section_header->sh_flags & SHF_ALLOC) furi_string_cat(flags_string, "A"); + if(section_header->sh_flags & SHF_EXECINSTR) furi_string_cat(flags_string, "X"); + if(section_header->sh_flags & SHF_MERGE) furi_string_cat(flags_string, "M"); + if(section_header->sh_flags & SHF_STRINGS) furi_string_cat(flags_string, "S"); + if(section_header->sh_flags & SHF_INFO_LINK) furi_string_cat(flags_string, "I"); + if(section_header->sh_flags & SHF_LINK_ORDER) furi_string_cat(flags_string, "L"); + if(section_header->sh_flags & SHF_OS_NONCONFORMING) furi_string_cat(flags_string, "O"); + if(section_header->sh_flags & SHF_GROUP) furi_string_cat(flags_string, "G"); + if(section_header->sh_flags & SHF_TLS) furi_string_cat(flags_string, "T"); + if(section_header->sh_flags & SHF_COMPRESSED) furi_string_cat(flags_string, "T"); + if(section_header->sh_flags & SHF_MASKOS) furi_string_cat(flags_string, "o"); + if(section_header->sh_flags & SHF_MASKPROC) furi_string_cat(flags_string, "p"); + if(section_header->sh_flags & SHF_ORDERED) furi_string_cat(flags_string, "R"); + if(section_header->sh_flags & SHF_EXCLUDE) furi_string_cat(flags_string, "E"); + + FURI_LOG_I( + TAG, + "Section %s: type: %ld, flags: %s", + name, + section_header->sh_type, + furi_string_get_cstr(flags_string)); + furi_string_free(flags_string); +#endif + + // ignore .ARM and .rel.ARM sections + // TODO: how to do it not by name? + // .ARM: type 0x70000001, flags SHF_ALLOC | SHF_LINK_ORDER + // .rel.ARM: type 0x9, flags SHT_REL + if(str_prefix(name, ".ARM") || str_prefix(name, ".rel.ARM")) { + FURI_LOG_D(TAG, "Ignoring ARM section"); + return SectionTypeUnused; + } + // Load allocable section if(section_header->sh_flags & SHF_ALLOC) { ELFSection* section_p = elf_file_get_or_put_section(elf, name); diff --git a/lib/nfc/helpers/mf_classic_dict.c b/lib/nfc/helpers/mf_classic_dict.c index 22fa956a0..a842ed921 100644 --- a/lib/nfc/helpers/mf_classic_dict.c +++ b/lib/nfc/helpers/mf_classic_dict.c @@ -69,9 +69,18 @@ MfClassicDict* mf_classic_dict_alloc(MfClassicDictType dict_type) { FuriString* next_line; next_line = furi_string_alloc(); while(true) { - if(!stream_read_line(dict->stream, next_line)) break; + if(!stream_read_line(dict->stream, next_line)) { + FURI_LOG_T(TAG, "No keys left in dict"); + break; + } + furi_string_trim(next_line); + FURI_LOG_T( + TAG, + "Read line: %s, len: %d", + furi_string_get_cstr(next_line), + furi_string_size(next_line)); if(furi_string_get_char(next_line, 0) == '#') continue; - if(furi_string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue; + if(furi_string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN - 1) continue; dict->total_keys++; } furi_string_free(next_line); diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index 9468925ee..66b9a7022 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -453,6 +453,54 @@ void nfc_worker_emulate_mf_ultralight(NfcWorker* nfc_worker) { } } +static void nfc_worker_mf_classic_key_attack( + NfcWorker* nfc_worker, + uint64_t key, + FuriHalNfcTxRxContext* tx_rx, + uint16_t start_sector) { + furi_assert(nfc_worker); + + MfClassicData* data = &nfc_worker->dev_data->mf_classic_data; + uint32_t total_sectors = mf_classic_get_total_sectors_num(data->type); + + furi_assert(start_sector < total_sectors); + + // Check every sector's A and B keys with the given key + for(size_t i = start_sector; i < total_sectors; i++) { + uint8_t block_num = mf_classic_get_sector_trailer_block_num_by_sector(i); + if(mf_classic_is_sector_read(data, i)) continue; + if(!mf_classic_is_key_found(data, i, MfClassicKeyA)) { + FURI_LOG_D( + TAG, + "Trying A key for sector %d, key: %04lx%08lx", + i, + (uint32_t)(key >> 32), + (uint32_t)key); + if(mf_classic_authenticate(tx_rx, block_num, key, MfClassicKeyA)) { + mf_classic_set_key_found(data, i, MfClassicKeyA, key); + FURI_LOG_D(TAG, "Key found"); + nfc_worker->callback(NfcWorkerEventFoundKeyA, nfc_worker->context); + } + } + if(!mf_classic_is_key_found(data, i, MfClassicKeyB)) { + FURI_LOG_D( + TAG, + "Trying B key for sector %d, key: %04lx%08lx", + i, + (uint32_t)(key >> 32), + (uint32_t)key); + if(mf_classic_authenticate(tx_rx, block_num, key, MfClassicKeyB)) { + mf_classic_set_key_found(data, i, MfClassicKeyB, key); + FURI_LOG_D(TAG, "Key found"); + nfc_worker->callback(NfcWorkerEventFoundKeyB, nfc_worker->context); + } + } + if(mf_classic_is_sector_read(data, i)) continue; + mf_classic_read_sector(tx_rx, data, i); + if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack) break; + } +} + void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { furi_assert(nfc_worker); furi_assert(nfc_worker->callback); @@ -485,6 +533,7 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { bool is_key_b_found = mf_classic_is_key_found(data, i, MfClassicKeyB); uint16_t key_index = 0; while(mf_classic_dict_get_next_key(dict, &key)) { + FURI_LOG_T(TAG, "Key %d", key_index); if(++key_index % NFC_DICT_KEY_BATCH_SIZE == 0) { nfc_worker->callback(NfcWorkerEventNewDictKeyBatch, nfc_worker->context); } @@ -506,15 +555,19 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { is_key_a_found = mf_classic_is_key_found(data, i, MfClassicKeyA); if(mf_classic_authenticate(&tx_rx, block_num, key, MfClassicKeyA)) { mf_classic_set_key_found(data, i, MfClassicKeyA, key); + FURI_LOG_D(TAG, "Key found"); nfc_worker->callback(NfcWorkerEventFoundKeyA, nfc_worker->context); + nfc_worker_mf_classic_key_attack(nfc_worker, key, &tx_rx, i + 1); } furi_hal_nfc_sleep(); } if(!is_key_b_found) { is_key_b_found = mf_classic_is_key_found(data, i, MfClassicKeyB); if(mf_classic_authenticate(&tx_rx, block_num, key, MfClassicKeyB)) { + FURI_LOG_D(TAG, "Key found"); mf_classic_set_key_found(data, i, MfClassicKeyB, key); nfc_worker->callback(NfcWorkerEventFoundKeyB, nfc_worker->context); + nfc_worker_mf_classic_key_attack(nfc_worker, key, &tx_rx, i + 1); } } if(is_key_a_found && is_key_b_found) break;