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

BIN
images/Nfc_10px.png


+ 2 - 0
scenes/weebo_scene_config.h

@@ -1,2 +1,4 @@
 ADD_SCENE(weebo, main_menu, MainMenu)
 ADD_SCENE(weebo, keys_missing, KeysMissing)
+ADD_SCENE(weebo, file_select, FileSelect)
+ADD_SCENE(weebo, saved_menu, SavedMenu)

+ 25 - 0
scenes/weebo_scene_file_select.c

@@ -0,0 +1,25 @@
+#include "../weebo_i.h"
+
+void weebo_scene_file_select_on_enter(void* context) {
+    Weebo* weebo = context;
+
+    // Process file_select return
+    weebo_set_loading_callback(weebo, weebo_show_loading_popup, weebo);
+    if(weebo_file_select(weebo)) {
+        scene_manager_next_scene(weebo->scene_manager, WeeboSceneSavedMenu);
+    } else {
+        scene_manager_search_and_switch_to_previous_scene(
+            weebo->scene_manager, WeeboSceneMainMenu);
+    }
+    weebo_set_loading_callback(weebo, NULL, weebo);
+}
+
+bool weebo_scene_file_select_on_event(void* context, SceneManagerEvent event) {
+    UNUSED(context);
+    UNUSED(event);
+    return false;
+}
+
+void weebo_scene_file_select_on_exit(void* context) {
+    UNUSED(context);
+}

+ 4 - 4
scenes/weebo_scene_main_menu.c

@@ -3,7 +3,7 @@
 #define TAG "SceneMainMenu"
 
 enum SubmenuIndex {
-    SubmenuIndexSelect = 0,
+    SubmenuIndexFileSelect = 0,
 };
 
 void weebo_scene_main_menu_submenu_callback(void* context, uint32_t index) {
@@ -17,7 +17,7 @@ void weebo_scene_main_menu_on_enter(void* context) {
     submenu_reset(submenu);
 
     submenu_add_item(
-        submenu, "Select", SubmenuIndexSelect, weebo_scene_main_menu_submenu_callback, weebo);
+        submenu, "Select", SubmenuIndexFileSelect, weebo_scene_main_menu_submenu_callback, weebo);
 
     submenu_set_selected_item(
         submenu, scene_manager_get_scene_state(weebo->scene_manager, WeeboSceneMainMenu));
@@ -30,8 +30,8 @@ bool weebo_scene_main_menu_on_event(void* context, SceneManagerEvent event) {
 
     if(event.type == SceneManagerEventTypeCustom) {
         scene_manager_set_scene_state(weebo->scene_manager, WeeboSceneMainMenu, event.event);
-        if(event.event == SubmenuIndexSelect) {
-            // scene_manager_next_scene(weebo->scene_manager, WeeboScenePassportNumberInput);
+        if(event.event == SubmenuIndexFileSelect) {
+            scene_manager_next_scene(weebo->scene_manager, WeeboSceneFileSelect);
             consumed = true;
         }
     }

+ 46 - 0
scenes/weebo_scene_saved_menu.c

@@ -0,0 +1,46 @@
+#include "../weebo_i.h"
+
+#define TAG "ScenesavedMenu"
+
+enum SubmenuIndex {
+    SubmenuIndexWrite = 0,
+};
+
+void weebo_scene_saved_menu_submenu_callback(void* context, uint32_t index) {
+    Weebo* weebo = context;
+    view_dispatcher_send_custom_event(weebo->view_dispatcher, index);
+}
+
+void weebo_scene_saved_menu_on_enter(void* context) {
+    Weebo* weebo = context;
+    Submenu* submenu = weebo->submenu;
+    submenu_reset(submenu);
+
+    submenu_add_item(
+        submenu, "Write", SubmenuIndexWrite, weebo_scene_saved_menu_submenu_callback, weebo);
+
+    submenu_set_selected_item(
+        submenu, scene_manager_get_scene_state(weebo->scene_manager, WeeboSceneSavedMenu));
+    view_dispatcher_switch_to_view(weebo->view_dispatcher, WeeboViewMenu);
+}
+
+bool weebo_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
+    Weebo* weebo = context;
+    bool consumed = false;
+
+    if(event.type == SceneManagerEventTypeCustom) {
+        scene_manager_set_scene_state(weebo->scene_manager, WeeboSceneSavedMenu, event.event);
+        if(event.event == SubmenuIndexWrite) {
+            // scene_manager_next_scene(weebo->scene_manager, WeeboSceneWrite);
+            consumed = true;
+        }
+    }
+
+    return consumed;
+}
+
+void weebo_scene_saved_menu_on_exit(void* context) {
+    Weebo* weebo = context;
+
+    submenu_reset(weebo->submenu);
+}

+ 84 - 0
weebo.c

@@ -4,6 +4,7 @@
 
 #define WEEBO_KEY_RETAIL_FILENAME "key_retail"
 
+/*
 uint8_t original[NTAG215_SIZE];
 uint8_t plain_base[NFC3D_AMIIBO_SIZE];
 uint8_t modified[NTAG215_SIZE];
@@ -14,6 +15,7 @@ void calculate_pwd(uint8_t* uid, uint8_t* pwd) {
     pwd[2] = uid[3] ^ uid[5] ^ 0xAA;
     pwd[3] = uid[4] ^ uid[6] ^ 0x55;
 }
+*/
 
 bool weebo_load_key_retail(Weebo* weebo) {
     FuriString* path = furi_string_alloc();
@@ -53,6 +55,88 @@ bool weebo_load_key_retail(Weebo* weebo) {
     return parsed;
 }
 
+bool weebo_load_figure(Weebo* weebo, FuriString* path, bool show_dialog) {
+    bool parsed = false;
+    uint8_t buffer[NTAG215_SIZE];
+    memset(buffer, 0, sizeof(buffer));
+
+    Storage* storage = furi_record_open(RECORD_STORAGE);
+    Stream* stream = file_stream_alloc(storage);
+
+    if(weebo->loading_cb) {
+        weebo->loading_cb(weebo->loading_cb_ctx, true);
+    }
+
+    // TODO: reject if the selected file is key_retail
+    do {
+        bool opened =
+            file_stream_open(stream, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING);
+        if(!opened) {
+            FURI_LOG_E(TAG, "Failed to open file");
+            break;
+        }
+
+        size_t bytes_read = stream_read(stream, buffer, sizeof(buffer));
+        if(bytes_read != sizeof(buffer)) {
+            FURI_LOG_E(TAG, "Insufficient data");
+            break;
+        }
+
+        if(!nfc3d_amiibo_unpack(&weebo->amiiboKeys, buffer, weebo->figure)) {
+            FURI_LOG_E(TAG, "Failed to unpack");
+            break;
+        }
+
+        parsed = true;
+    } while(false);
+
+    file_stream_close(stream);
+    furi_record_close(RECORD_STORAGE);
+
+    if(weebo->loading_cb) {
+        weebo->loading_cb(weebo->loading_cb_ctx, false);
+    }
+
+    if((!parsed) && (show_dialog)) {
+        dialog_message_show_storage_error(weebo->dialogs, "Can not parse\nfile");
+    }
+
+    return parsed;
+}
+
+void weebo_set_loading_callback(Weebo* weebo, WeeboLoadingCallback callback, void* context) {
+    furi_assert(weebo);
+
+    weebo->loading_cb = callback;
+    weebo->loading_cb_ctx = context;
+}
+
+bool weebo_file_select(Weebo* weebo) {
+    furi_assert(weebo);
+    bool res = false;
+
+    FuriString* weebo_app_folder = furi_string_alloc_set(STORAGE_APP_DATA_PATH_PREFIX);
+
+    DialogsFileBrowserOptions browser_options;
+    dialog_file_browser_set_basic_options(&browser_options, ".bin", &I_Nfc_10px);
+    browser_options.base_path = STORAGE_APP_DATA_PATH_PREFIX;
+
+    res = dialog_file_browser_show(
+        weebo->dialogs, weebo->load_path, weebo_app_folder, &browser_options);
+
+    furi_string_free(weebo_app_folder);
+    if(res) {
+        FuriString* filename;
+        filename = furi_string_alloc();
+        path_extract_filename(weebo->load_path, filename, true);
+        strncpy(weebo->file_name, furi_string_get_cstr(filename), WEEBO_FILE_NAME_MAX_LENGTH);
+        res = weebo_load_figure(weebo, weebo->load_path, true);
+        furi_string_free(filename);
+    }
+
+    return res;
+}
+
 bool weebo_custom_event_callback(void* context, uint32_t event) {
     furi_assert(context);
     Weebo* weebo = context;

+ 0 - 2
weebo.h

@@ -1,5 +1,3 @@
 #pragma once
 
 typedef struct Weebo Weebo;
-
-bool weebo_load_key_retail(Weebo* weebo);

+ 11 - 0
weebo_i.h

@@ -19,6 +19,7 @@
 
 #include <input/input.h>
 #include <lib/flipper_format/flipper_format.h>
+#include <lib/toolbox/path.h>
 
 #include <lib/nfc/nfc.h>
 #include <nfc/nfc_poller.h>
@@ -51,6 +52,8 @@ enum WeeboCustomEvent {
     WeeboCustomEventNumberInputDone,
 };
 
+typedef void (*WeeboLoadingCallback)(void* context, bool state);
+
 struct Weebo {
     ViewDispatcher* view_dispatcher;
     Gui* gui;
@@ -80,6 +83,11 @@ struct Weebo {
 
     bool keys_loaded;
     nfc3d_amiibo_keys amiiboKeys;
+
+    WeeboLoadingCallback loading_cb;
+    void* loading_cb_ctx;
+
+    uint8_t figure[NFC3D_AMIIBO_SIZE];
 };
 
 typedef enum {
@@ -101,3 +109,6 @@ void weebo_blink_start(Weebo* weebo);
 void weebo_blink_stop(Weebo* weebo);
 
 void weebo_show_loading_popup(void* context, bool show);
+
+void weebo_set_loading_callback(Weebo* weebo, WeeboLoadingCallback callback, void* context);
+bool weebo_file_select(Weebo* weebo);