Eric Betts 8 месяцев назад
Родитель
Сommit
81a66ae9ef

BIN
images/DolphinNice_96x59.png


+ 2 - 0
scenes/weebo_scene_config.h

@@ -6,3 +6,5 @@ ADD_SCENE(weebo, write, Write)
 ADD_SCENE(weebo, write_card_success, WriteCardSuccess)
 ADD_SCENE(weebo, emulate, Emulate)
 ADD_SCENE(weebo, info, Info)
+ADD_SCENE(weebo, save_name, SaveName)
+ADD_SCENE(weebo, save_success, SaveSuccess)

+ 1 - 42
scenes/weebo_scene_emulate.c

@@ -3,47 +3,6 @@
 
 #define TAG "SceneEmulate"
 
-void weebo_scene_emulate_calculate_pwd(uint8_t* uid, uint8_t* pwd) {
-    pwd[0] = uid[1] ^ uid[3] ^ 0xAA;
-    pwd[1] = uid[2] ^ uid[4] ^ 0x55;
-    pwd[2] = uid[3] ^ uid[5] ^ 0xAA;
-    pwd[3] = uid[4] ^ uid[6] ^ 0x55;
-}
-
-void weebo_scene_emulate_remix(Weebo* weebo) {
-    uint8_t PWD[4];
-    uint8_t UID[8];
-    uint8_t modified[NTAG215_SIZE];
-    MfUltralightData* data = mf_ultralight_alloc();
-    nfc_device_copy_data(weebo->nfc_device, NfcProtocolMfUltralight, data);
-
-    //random uid
-    FURI_LOG_D(TAG, "Generating random UID");
-    UID[0] = 0x04;
-    furi_hal_random_fill_buf(UID + 1, 6);
-    UID[7] = UID[3] ^ UID[4] ^ UID[5] ^ UID[6];
-    memcpy(weebo->figure + NFC3D_UID_OFFSET, UID, 8);
-    memcpy(data->iso14443_3a_data->uid, UID, 7);
-
-    //pack
-    nfc3d_amiibo_pack(&weebo->amiiboKeys, weebo->figure, modified);
-
-    //copy data in
-    for(size_t i = 0; i < 130; i++) {
-        memcpy(
-            data->page[i].data, modified + i * MF_ULTRALIGHT_PAGE_SIZE, MF_ULTRALIGHT_PAGE_SIZE);
-    }
-
-    //new pwd
-    weebo_scene_emulate_calculate_pwd(data->iso14443_3a_data->uid, PWD);
-    memcpy(data->page[133].data, PWD, sizeof(PWD));
-
-    //set data
-    nfc_device_set_data(weebo->nfc_device, NfcProtocolMfUltralight, data);
-
-    mf_ultralight_free(data);
-}
-
 void weebo_scene_emulate_widget_callback(GuiButtonType result, InputType type, void* context) {
     furi_assert(context);
     Weebo* weebo = context;
@@ -111,7 +70,7 @@ bool weebo_scene_emulate_on_event(void* context, SceneManagerEvent event) {
             nfc_listener_free(weebo->listener);
             weebo->listener = NULL;
 
-            weebo_scene_emulate_remix(weebo);
+            weebo_remix(weebo);
             //start listener
             FURI_LOG_D(TAG, "Starting listener");
             const MfUltralightData* data =

+ 94 - 0
scenes/weebo_scene_save_name.c

@@ -0,0 +1,94 @@
+#include "../weebo_i.h"
+#include <lib/toolbox/name_generator.h>
+#include <gui/modules/validators.h>
+#include <toolbox/path.h>
+
+#define NFC_APP_EXTENSION     ".nfc"
+#define NFC_APP_PATH_PREFIX   "/ext/nfc"
+#define WEEBO_APP_FILE_PREFIX "weebo_"
+
+#define TAG "WeeboSceneSaveName"
+
+void weebo_scene_save_name_text_input_callback(void* context) {
+    Weebo* weebo = context;
+
+    view_dispatcher_send_custom_event(weebo->view_dispatcher, WeeboCustomEventTextInputDone);
+}
+
+void weebo_scene_save_name_on_enter(void* context) {
+    Weebo* weebo = context;
+
+    // Setup view
+    TextInput* text_input = weebo->text_input;
+    bool file_name_empty = false;
+    if(!strcmp(weebo->file_name, "")) {
+        name_generator_make_auto(
+            weebo->text_store, sizeof(weebo->text_store), WEEBO_APP_FILE_PREFIX);
+        file_name_empty = true;
+    } else {
+        weebo_text_store_set(weebo, weebo->file_name);
+    }
+    text_input_set_header_text(text_input, "Name the card");
+    text_input_set_result_callback(
+        text_input,
+        weebo_scene_save_name_text_input_callback,
+        weebo,
+        weebo->text_store,
+        sizeof(weebo->text_store),
+        file_name_empty);
+
+    FuriString* folder_path;
+    folder_path = furi_string_alloc_set(NFC_APP_PATH_PREFIX);
+
+    if(furi_string_end_with(weebo->load_path, NFC_APP_EXTENSION)) {
+        path_extract_dirname(furi_string_get_cstr(weebo->load_path), folder_path);
+    }
+
+    ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(
+        furi_string_get_cstr(folder_path), NFC_APP_EXTENSION, weebo->file_name);
+    text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
+
+    view_dispatcher_switch_to_view(weebo->view_dispatcher, WeeboViewTextInput);
+
+    furi_string_free(folder_path);
+}
+
+bool weebo_scene_save_name_on_event(void* context, SceneManagerEvent event) {
+    Weebo* weebo = context;
+    bool consumed = false;
+
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == WeeboCustomEventTextInputDone) {
+            strlcpy(weebo->file_name, weebo->text_store, strlen(weebo->text_store) + 1);
+
+            FuriString* path = furi_string_alloc_set(NFC_APP_PATH_PREFIX);
+            if(furi_string_end_with(weebo->load_path, NFC_APP_EXTENSION)) {
+                path_extract_dirname(furi_string_get_cstr(weebo->load_path), path);
+            }
+            furi_string_cat_printf(path, "/%s%s", weebo->file_name, NFC_APP_EXTENSION);
+            FURI_LOG_D(TAG, "Saving to %s", furi_string_get_cstr(path));
+
+            if(nfc_device_save(weebo->nfc_device, furi_string_get_cstr(path))) {
+                scene_manager_next_scene(weebo->scene_manager, WeeboSceneSaveSuccess);
+                consumed = true;
+            } else {
+                consumed = scene_manager_search_and_switch_to_previous_scene(
+                    weebo->scene_manager, WeeboSceneMainMenu);
+            }
+
+            furi_string_free(path);
+        }
+    }
+    return consumed;
+}
+
+void weebo_scene_save_name_on_exit(void* context) {
+    Weebo* weebo = context;
+
+    // Clear view
+    void* validator_context = text_input_get_validator_callback_context(weebo->text_input);
+    text_input_set_validator(weebo->text_input, NULL, NULL);
+    validator_is_file_free(validator_context);
+
+    text_input_reset(weebo->text_input);
+}

+ 42 - 0
scenes/weebo_scene_save_success.c

@@ -0,0 +1,42 @@
+#include "../weebo_i.h"
+#include <dolphin/dolphin.h>
+
+void weebo_scene_save_success_popup_callback(void* context) {
+    Weebo* weebo = context;
+    view_dispatcher_send_custom_event(weebo->view_dispatcher, WeeboCustomEventViewExit);
+}
+
+void weebo_scene_save_success_on_enter(void* context) {
+    Weebo* weebo = context;
+    dolphin_deed(DolphinDeedNfcSave);
+
+    // Setup view
+    Popup* popup = weebo->popup;
+    popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
+    popup_set_header(popup, "Saved!", 13, 22, AlignLeft, AlignBottom);
+    popup_set_timeout(popup, 1500);
+    popup_set_context(popup, weebo);
+    popup_set_callback(popup, weebo_scene_save_success_popup_callback);
+    popup_enable_timeout(popup);
+    view_dispatcher_switch_to_view(weebo->view_dispatcher, WeeboViewPopup);
+}
+
+bool weebo_scene_save_success_on_event(void* context, SceneManagerEvent event) {
+    Weebo* weebo = context;
+    bool consumed = false;
+
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == WeeboCustomEventViewExit) {
+            consumed = scene_manager_search_and_switch_to_previous_scene(
+                weebo->scene_manager, WeeboSceneSavedMenu);
+        }
+    }
+    return consumed;
+}
+
+void weebo_scene_save_success_on_exit(void* context) {
+    Weebo* weebo = context;
+
+    // Clear view
+    popup_reset(weebo->popup);
+}

+ 2 - 1
scenes/weebo_scene_saved_menu.c

@@ -50,7 +50,8 @@ bool weebo_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
             scene_manager_next_scene(weebo->scene_manager, WeeboSceneEmulate);
             consumed = true;
         } else if(event.event == SubmenuIndexDuplicate) {
-            //scene_manager_next_scene(weebo->scene_manager, WeeboSceneDuplicate);
+            weebo_remix(weebo);
+            scene_manager_next_scene(weebo->scene_manager, WeeboSceneSaveName);
             consumed = true;
         } else if(event.event == SubmenuIndexInfo) {
             scene_manager_next_scene(weebo->scene_manager, WeeboSceneInfo);

+ 1 - 8
scenes/weebo_scene_write.c

@@ -23,13 +23,6 @@ enum NTAG215Pages {
     total = 135
 };
 
-void weebo_scene_write_calculate_pwd(uint8_t* uid, uint8_t* pwd) {
-    pwd[0] = uid[1] ^ uid[3] ^ 0xAA;
-    pwd[1] = uid[2] ^ uid[4] ^ 0x55;
-    pwd[2] = uid[3] ^ uid[5] ^ 0xAA;
-    pwd[3] = uid[4] ^ uid[6] ^ 0x55;
-}
-
 NfcCommand weebo_scene_write_poller_callback(NfcGenericEvent event, void* context) {
     furi_assert(event.protocol == NfcProtocolMfUltralight);
     Weebo* weebo = context;
@@ -61,7 +54,7 @@ NfcCommand weebo_scene_write_poller_callback(NfcGenericEvent event, void* contex
         view_dispatcher_send_custom_event(weebo->view_dispatcher, WeeboCustomEventCardDetected);
 
         uint8_t PWD[4];
-        weebo_scene_write_calculate_pwd(data->iso14443_3a_data->uid, PWD);
+        weebo_calculate_pwd(data->iso14443_3a_data->uid, PWD);
 
         for(size_t p = 0; p < 2; p++) {
             for(size_t i = 0; i < MF_ULTRALIGHT_PAGE_SIZE; i++) {

+ 6 - 7
weebo.c

@@ -5,6 +5,8 @@
 #define WEEBO_KEY_RETAIL_FILENAME "key_retail"
 #define FIGURE_ID_LIST            APP_ASSETS_PATH("figure_ids.nfc")
 #define UNPACKED_FIGURE_ID        0x1dc
+#define NFC_APP_EXTENSION         ".nfc"
+#define NFC_APP_PATH_PREFIX       "/ext/nfc"
 
 static const char* nfc_resources_header = "Flipper NFC resources";
 static const uint32_t nfc_resources_file_version = 1;
@@ -80,10 +82,7 @@ bool weebo_load_figure(Weebo* weebo, FuriString* path, bool show_dialog) {
 
         uint8_t* uid = data->iso14443_3a_data->uid;
         uint8_t pwd[4];
-        pwd[0] = uid[1] ^ uid[3] ^ 0xAA;
-        pwd[1] = uid[2] ^ uid[4] ^ 0x55;
-        pwd[2] = uid[3] ^ uid[5] ^ 0xAA;
-        pwd[3] = uid[4] ^ uid[6] ^ 0x55;
+        weebo_calculate_pwd(uid, pwd);
 
         if(memcmp(data->page[133].data, pwd, sizeof(pwd)) != 0) {
             furi_string_printf(reason, "Wrong password");
@@ -178,12 +177,12 @@ bool weebo_file_select(Weebo* weebo) {
     } else if(storage_dir_exists(weebo->storage, "/ext/nfc/amiibos")) {
         weebo_app_folder = furi_string_alloc_set("/ext/nfc/amiibos");
     } else {
-        weebo_app_folder = furi_string_alloc_set("/ext/nfc");
+        weebo_app_folder = furi_string_alloc_set(NFC_APP_PATH_PREFIX);
     }
 
     DialogsFileBrowserOptions browser_options;
-    dialog_file_browser_set_basic_options(&browser_options, ".nfc", &I_Nfc_10px);
-    browser_options.base_path = STORAGE_APP_DATA_PATH_PREFIX;
+    dialog_file_browser_set_basic_options(&browser_options, NFC_APP_EXTENSION, &I_Nfc_10px);
+    browser_options.base_path = NFC_APP_PATH_PREFIX;
 
     res = dialog_file_browser_show(
         weebo->dialogs, weebo->load_path, weebo_app_folder, &browser_options);

+ 44 - 0
weebo_common.c

@@ -0,0 +1,44 @@
+#include "weebo_common.h"
+
+#define TAG "WeeboCommon"
+
+void weebo_calculate_pwd(uint8_t* uid, uint8_t* pwd) {
+    pwd[0] = uid[1] ^ uid[3] ^ 0xAA;
+    pwd[1] = uid[2] ^ uid[4] ^ 0x55;
+    pwd[2] = uid[3] ^ uid[5] ^ 0xAA;
+    pwd[3] = uid[4] ^ uid[6] ^ 0x55;
+}
+
+void weebo_remix(Weebo* weebo) {
+    uint8_t PWD[4];
+    uint8_t UID[8];
+    uint8_t modified[NTAG215_SIZE];
+    MfUltralightData* data = mf_ultralight_alloc();
+    nfc_device_copy_data(weebo->nfc_device, NfcProtocolMfUltralight, data);
+
+    //random uid
+    FURI_LOG_D(TAG, "Generating random UID");
+    UID[0] = 0x04;
+    furi_hal_random_fill_buf(UID + 1, 6);
+    UID[7] = UID[3] ^ UID[4] ^ UID[5] ^ UID[6];
+    memcpy(weebo->figure + NFC3D_UID_OFFSET, UID, 8);
+    memcpy(data->iso14443_3a_data->uid, UID, 7);
+
+    //pack
+    nfc3d_amiibo_pack(&weebo->amiiboKeys, weebo->figure, modified);
+
+    //copy data in
+    for(size_t i = 0; i < 130; i++) {
+        memcpy(
+            data->page[i].data, modified + i * MF_ULTRALIGHT_PAGE_SIZE, MF_ULTRALIGHT_PAGE_SIZE);
+    }
+
+    //new pwd
+    weebo_calculate_pwd(data->iso14443_3a_data->uid, PWD);
+    memcpy(data->page[133].data, PWD, sizeof(PWD));
+
+    //set data
+    nfc_device_set_data(weebo->nfc_device, NfcProtocolMfUltralight, data);
+
+    mf_ultralight_free(data);
+}

+ 7 - 0
weebo_common.h

@@ -0,0 +1,7 @@
+#pragma once
+
+#include <furi.h>
+#include <weebo_i.h>
+
+void weebo_calculate_pwd(uint8_t* uid, uint8_t* pwd);
+void weebo_remix(Weebo* weebo);

+ 1 - 0
weebo_i.h

@@ -37,6 +37,7 @@
 #include <amiibo.h>
 
 #include "weebo.h"
+#include "weebo_common.h"
 #include "scenes/weebo_scene.h"
 
 #define WEEBO_TEXT_STORE_SIZE      128