diff --git a/application.fam b/application.fam index ec42fbc..403ac57 100644 --- a/application.fam +++ b/application.fam @@ -25,6 +25,7 @@ _MAIN_APP_SOURCES = [ "!protopirate_emulate_plugin.c", "!protopirate_psa_bf_plugin.c", "!protopirate_saved_info_plugin.c", + "!protopirate_about_plugin.c", "!protopirate_config_plugin.c", "protocols/protocol_items.c", "protocols/protocols_common.c", @@ -63,7 +64,7 @@ App( # --- RX protocol plugins --- App( - appid="protopirate_am_plugin", + appid="pp_am", apptype=FlipperAppType.PLUGIN, entry_point="protopirate_am_plugin_ep", requires=["proto_pirate"], @@ -92,7 +93,7 @@ App( ) App( - appid="protopirate_am_vag_plugin", + appid="pp_am_vag", apptype=FlipperAppType.PLUGIN, entry_point="protopirate_am_vag_plugin_ep", requires=["proto_pirate"], @@ -107,7 +108,7 @@ App( ) App( - appid="protopirate_fm_plugin", + appid="pp_fm", apptype=FlipperAppType.PLUGIN, entry_point="protopirate_fm_plugin_ep", requires=["proto_pirate"], @@ -131,7 +132,7 @@ App( ) App( - appid="protopirate_fm_f4_plugin", + appid="pp_fm_f4", apptype=FlipperAppType.PLUGIN, entry_point="protopirate_fm_f4_plugin_ep", requires=["proto_pirate"], @@ -148,7 +149,7 @@ App( ) App( - appid="protopirate_fm_honda1_plugin", + appid="pp_fm_honda1", apptype=FlipperAppType.PLUGIN, entry_point="protopirate_fm_honda1_plugin_ep", requires=["proto_pirate"], @@ -183,7 +184,7 @@ def ProtoPirateTxProtocolPlugin( return App( - appid=f"protopirate_tx_{key}_plugin", + appid=f"pp_tx_{key}", apptype=FlipperAppType.PLUGIN, entry_point="protopirate_tx_protocol_plugin_ep", requires=["proto_pirate"], @@ -362,7 +363,7 @@ ProtoPirateTxProtocolPlugin( # --- Tool / scene plugins --- App( - appid="protopirate_sub_decode_plugin", + appid="pp_sub_decode", apptype=FlipperAppType.PLUGIN, entry_point="protopirate_sub_decode_plugin_ep", requires=["proto_pirate"], @@ -381,7 +382,7 @@ App( if _ENABLE_TIMING_TUNER: App( - appid="protopirate_timing_tuner_plugin", + appid="pp_timing_tuner", apptype=FlipperAppType.PLUGIN, entry_point="protopirate_timing_tuner_plugin_ep", requires=["proto_pirate"], @@ -395,7 +396,7 @@ if _ENABLE_TIMING_TUNER: if _ENABLE_EMULATE: App( - appid="protopirate_emulate_plugin", + appid="pp_emulate", apptype=FlipperAppType.PLUGIN, entry_point="protopirate_emulate_plugin_ep", requires=["proto_pirate"], @@ -407,7 +408,7 @@ if _ENABLE_EMULATE: ) App( - appid="protopirate_psa_bf_plugin", + appid="pp_bf", apptype=FlipperAppType.PLUGIN, entry_point="protopirate_psa_bf_plugin_ep", requires=["proto_pirate"], @@ -425,7 +426,7 @@ App( ) App( - appid="protopirate_config_plugin", + appid="pp_config", apptype=FlipperAppType.PLUGIN, entry_point="protopirate_config_plugin_ep", requires=["proto_pirate"], @@ -435,12 +436,12 @@ App( "helpers/variable_item_list.c", "scenes/plugins/protopirate_config_plugin.c", ], - fap_icon_assets="images", + fap_icon_assets="helpers/variable_item_list_images", fal_embedded=True, ) App( - appid="protopirate_saved_info_plugin", + appid="pp_saved_info", apptype=FlipperAppType.PLUGIN, entry_point="protopirate_saved_info_plugin_ep", requires=["proto_pirate"], @@ -451,4 +452,17 @@ App( ], fap_icon_assets="images", fal_embedded=True, +) + +App( + appid="pp_about", + apptype=FlipperAppType.PLUGIN, + entry_point="protopirate_about_plugin_ep", + requires=["proto_pirate"], + cdefines=["PROTOPIRATE_ABOUT_PLUGIN_BUILD"], + sources=[ + "scenes/plugins/protopirate_about_plugin.c", + ], + fap_icon_assets="images", + fal_embedded=True, ) \ No newline at end of file diff --git a/helpers/protopirate_models.c b/helpers/protopirate_models.c index 39c1277..9f50f73 100644 --- a/helpers/protopirate_models.c +++ b/helpers/protopirate_models.c @@ -1,6 +1,6 @@ #include "protopirate_models.h" -#define TAG "ProtoPirateModels" +#define TAG "PPModels" #define PROTOPIRATE_MODELS_FILE APP_ASSETS_PATH("models.txt") @@ -73,7 +73,7 @@ bool car_model_get_by_index( //Read the Model Name. if(!flipper_format_read_string(ff, model_name_index, model_name)) { - FURI_LOG_E("ProtoPirate", "Failed to read %s", model_name_index); + FURI_LOG_E(TAG, "Failed to read %s", model_name_index); break; } @@ -168,7 +168,7 @@ bool car_model_get_by_index( preset_data_size > 0) { if(preset_data_size >= 1024) { FURI_LOG_E( - "ProtoPirate", + TAG, "%s too large: %lu", preset_data_index, (unsigned long)preset_data_size); @@ -178,7 +178,7 @@ bool car_model_get_by_index( preset_data = malloc(preset_data_size); if(!preset_data) { FURI_LOG_E( - "ProtoPirate", + TAG, "Malloc failed: %s (%lu bytes)", preset_data_index, (unsigned long)preset_data_size); diff --git a/helpers/protopirate_protocol_plugin_host.c b/helpers/protopirate_protocol_plugin_host.c index 14b8b0e..d5b2bd3 100644 --- a/helpers/protopirate_protocol_plugin_host.c +++ b/helpers/protopirate_protocol_plugin_host.c @@ -6,7 +6,7 @@ #include #include -#define TAG "ProtoPirateProtocolPlugin" +#define TAG "PPProtocolPlugin" #ifdef ENABLE_EMULATE_FEATURE #define PROTOPIRATE_TX_PLUGIN_PATH_MAX 160U #endif @@ -14,16 +14,16 @@ static const char* protopirate_get_registry_plugin_path(ProtoPirateProtocolRegistryRoute route) { switch(route) { case ProtoPirateProtocolRegistryRouteAMVag: - return APP_ASSETS_PATH("plugins/protopirate_am_vag_plugin.fal"); + return APP_ASSETS_PATH("plugins/pp_am_vag.fal"); case ProtoPirateProtocolRegistryRouteFMDefault: - return APP_ASSETS_PATH("plugins/protopirate_fm_plugin.fal"); + return APP_ASSETS_PATH("plugins/pp_fm.fal"); case ProtoPirateProtocolRegistryRouteFMF4: - return APP_ASSETS_PATH("plugins/protopirate_fm_f4_plugin.fal"); + return APP_ASSETS_PATH("plugins/pp_fm_f4.fal"); case ProtoPirateProtocolRegistryRouteFMHonda1: - return APP_ASSETS_PATH("plugins/protopirate_fm_honda1_plugin.fal"); + return APP_ASSETS_PATH("plugins/pp_fm_honda1.fal"); case ProtoPirateProtocolRegistryRouteAMDefault: default: - return APP_ASSETS_PATH("plugins/protopirate_am_plugin.fal"); + return APP_ASSETS_PATH("plugins/pp_am.fal"); } } @@ -36,11 +36,8 @@ static bool protopirate_build_tx_protocol_plugin_path( return false; } - int written = snprintf( - plugin_path, - plugin_path_size, - APP_ASSETS_PATH("plugins/protopirate_tx_%s_plugin.fal"), - tx_key); + int written = + snprintf(plugin_path, plugin_path_size, APP_ASSETS_PATH("plugins/pp_tx_%s.fal"), tx_key); return (written > 0) && ((size_t)written < plugin_path_size); } #endif diff --git a/helpers/protopirate_psa_bf_host.c b/helpers/protopirate_psa_bf_host.c index 16247fb..0052549 100644 --- a/helpers/protopirate_psa_bf_host.c +++ b/helpers/protopirate_psa_bf_host.c @@ -9,8 +9,8 @@ #include #include -#define TAG "ProtoPiratePsaBfHost" -#define PSA_BF_PLUGIN_PATH APP_ASSETS_PATH("plugins/protopirate_psa_bf_plugin.fal") +#define TAG "PPPsaBfHost" +#define PSA_BF_PLUGIN_PATH APP_ASSETS_PATH("plugins/pp_bf.fal") static bool host_ensure_widget(void* app) { return protopirate_ensure_widget((ProtoPirateApp*)app); diff --git a/helpers/protopirate_radio.c b/helpers/protopirate_radio.c index d6cc1b9..d83e082 100644 --- a/helpers/protopirate_radio.c +++ b/helpers/protopirate_radio.c @@ -4,7 +4,7 @@ #include #include -#define TAG "ProtoPirateRadio" +#define TAG "PPRadio" static void protopirate_radio_free_receiver(ProtoPirateApp* app) { furi_check(app); diff --git a/helpers/protopirate_saved_match.c b/helpers/protopirate_saved_match.c index fb47f46..cf6faa4 100644 --- a/helpers/protopirate_saved_match.c +++ b/helpers/protopirate_saved_match.c @@ -4,7 +4,7 @@ #include #include -#define TAG "ProtoPirateMatch" +#define TAG "PPMatch" #define CNT_MATCH_MARGIN 50 bool protopirate_saved_match_signal( diff --git a/helpers/protopirate_settings.c b/helpers/protopirate_settings.c index 4a53313..ee1b0e0 100644 --- a/helpers/protopirate_settings.c +++ b/helpers/protopirate_settings.c @@ -7,7 +7,7 @@ #include "../defines.h" #include "../protocols/protocols_common.h" -#define TAG "ProtoPirateSettings" +#define TAG "PPSettings" #define SETTINGS_FILE_HEADER "ProtoPirate Settings" #define SETTINGS_FILE_VERSION 1 diff --git a/helpers/protopirate_storage.c b/helpers/protopirate_storage.c index 6c4faa1..00092ba 100644 --- a/helpers/protopirate_storage.c +++ b/helpers/protopirate_storage.c @@ -7,7 +7,7 @@ #include #include -#define TAG "ProtoPirateStorage" +#define TAG "PPStorage" bool protopirate_storage_init(void) { Storage* storage = furi_record_open(RECORD_STORAGE); diff --git a/helpers/protopirate_tool_scene_host.c b/helpers/protopirate_tool_scene_host.c index 0ad0d36..44f9064 100644 --- a/helpers/protopirate_tool_scene_host.c +++ b/helpers/protopirate_tool_scene_host.c @@ -5,11 +5,11 @@ #include #include -#define TAG "ProtoPirateToolScene" +#define TAG "PPToolScene" -#define SUB_DECODE_PLUGIN_PATH APP_ASSETS_PATH("plugins/protopirate_sub_decode_plugin.fal") +#define SUB_DECODE_PLUGIN_PATH APP_ASSETS_PATH("plugins/pp_sub_decode.fal") #ifdef ENABLE_TIMING_TUNER_SCENE -#define TIMING_TUNER_PLUGIN_PATH APP_ASSETS_PATH("plugins/protopirate_timing_tuner_plugin.fal") +#define TIMING_TUNER_PLUGIN_PATH APP_ASSETS_PATH("plugins/pp_timing_tuner.fal") #endif static const char* protopirate_tool_scene_plugin_path(ProtoPirateToolScenePluginKind kind) { diff --git a/helpers/protopirate_txrx.c b/helpers/protopirate_txrx.c index f2f81d1..ffeda9d 100644 --- a/helpers/protopirate_txrx.c +++ b/helpers/protopirate_txrx.c @@ -6,7 +6,7 @@ #include -#define TAG "ProtoPirateTxRx" +#define TAG "PPTxRx" void protopirate_rx_stack_teardown_for_registry_switch(ProtoPirateApp* app) { furi_check(app); diff --git a/helpers/protopirate_views.c b/helpers/protopirate_views.c index fc2b0a3..c900eb0 100644 --- a/helpers/protopirate_views.c +++ b/helpers/protopirate_views.c @@ -3,7 +3,7 @@ #include -#define TAG "ProtoPirateViews" +#define TAG "PPViews" bool protopirate_ensure_widget(ProtoPirateApp* app) { furi_check(app); diff --git a/helpers/variable_item_list.c b/helpers/variable_item_list.c index 3f14504..e9f2f9a 100644 --- a/helpers/variable_item_list.c +++ b/helpers/variable_item_list.c @@ -6,7 +6,7 @@ #include #ifdef PROTOPIRATE_CONFIG_PLUGIN_BUILD -#include "protopirate_config_plugin_icons.h" +#include "pp_config_icons.h" #else #include "proto_pirate_icons.h" #endif diff --git a/images/Lock_7x8.png b/helpers/variable_item_list_images/Lock_7x8.png similarity index 100% rename from images/Lock_7x8.png rename to helpers/variable_item_list_images/Lock_7x8.png diff --git a/images/WarningDolphin_45x42.png b/helpers/variable_item_list_images/WarningDolphin_45x42.png similarity index 100% rename from images/WarningDolphin_45x42.png rename to helpers/variable_item_list_images/WarningDolphin_45x42.png diff --git a/protocols/plugins/protopirate_am_plugin.c b/protocols/plugins/protopirate_am_plugin.c index 4404850..cc71995 100644 --- a/protocols/plugins/protopirate_am_plugin.c +++ b/protocols/plugins/protopirate_am_plugin.c @@ -41,7 +41,7 @@ static const SubGhzProtocolRegistry protopirate_protocol_registry_am = { }; static const ProtoPirateProtocolPlugin protopirate_am_plugin = { - .plugin_name = "ProtoPirate AM Default Registry", + .plugin_name = "AM Registry", .kind = ProtoPirateProtocolPluginKindRx, .route = ProtoPirateProtocolRegistryRouteAMDefault, .registry = &protopirate_protocol_registry_am, diff --git a/protocols/plugins/protopirate_am_vag_plugin.c b/protocols/plugins/protopirate_am_vag_plugin.c index 45611b9..752360a 100644 --- a/protocols/plugins/protopirate_am_vag_plugin.c +++ b/protocols/plugins/protopirate_am_vag_plugin.c @@ -13,7 +13,7 @@ static const SubGhzProtocolRegistry protopirate_protocol_registry_am_vag = { }; static const ProtoPirateProtocolPlugin protopirate_am_vag_plugin = { - .plugin_name = "ProtoPirate AM VAG Registry", + .plugin_name = "AM VAG Registry", .kind = ProtoPirateProtocolPluginKindRx, .route = ProtoPirateProtocolRegistryRouteAMVag, .registry = &protopirate_protocol_registry_am_vag, diff --git a/protocols/plugins/protopirate_fm_f4_plugin.c b/protocols/plugins/protopirate_fm_f4_plugin.c index a13cc98..b3ee0fa 100644 --- a/protocols/plugins/protopirate_fm_f4_plugin.c +++ b/protocols/plugins/protopirate_fm_f4_plugin.c @@ -19,7 +19,7 @@ static const SubGhzProtocolRegistry protopirate_protocol_registry_fm_f4 = { }; static const ProtoPirateProtocolPlugin protopirate_fm_f4_plugin = { - .plugin_name = "ProtoPirate FM F4 Registry", + .plugin_name = "FM F4 Registry", .kind = ProtoPirateProtocolPluginKindRx, .route = ProtoPirateProtocolRegistryRouteFMF4, .registry = &protopirate_protocol_registry_fm_f4, diff --git a/protocols/plugins/protopirate_fm_honda1_plugin.c b/protocols/plugins/protopirate_fm_honda1_plugin.c index f4892f0..9bfdb4c 100644 --- a/protocols/plugins/protopirate_fm_honda1_plugin.c +++ b/protocols/plugins/protopirate_fm_honda1_plugin.c @@ -13,7 +13,7 @@ static const SubGhzProtocolRegistry protopirate_protocol_registry_fm_honda1 = { }; static const ProtoPirateProtocolPlugin protopirate_fm_honda1_plugin = { - .plugin_name = "ProtoPirate FM Honda1 Registry", + .plugin_name = "FM Honda1 Registry", .kind = ProtoPirateProtocolPluginKindRx, .route = ProtoPirateProtocolRegistryRouteFMHonda1, .registry = &protopirate_protocol_registry_fm_honda1, diff --git a/protocols/plugins/protopirate_fm_plugin.c b/protocols/plugins/protopirate_fm_plugin.c index 5f31bab..8cba9d5 100644 --- a/protocols/plugins/protopirate_fm_plugin.c +++ b/protocols/plugins/protopirate_fm_plugin.c @@ -29,7 +29,7 @@ static const SubGhzProtocolRegistry protopirate_protocol_registry_fm = { }; static const ProtoPirateProtocolPlugin protopirate_fm_plugin = { - .plugin_name = "ProtoPirate FM Default Registry", + .plugin_name = "FM Default Registry", .kind = ProtoPirateProtocolPluginKindRx, .route = ProtoPirateProtocolRegistryRouteFMDefault, .registry = &protopirate_protocol_registry_fm, diff --git a/protocols/protocol_items.c b/protocols/protocol_items.c index d72ae35..40c9a94 100644 --- a/protocols/protocol_items.c +++ b/protocols/protocol_items.c @@ -5,7 +5,7 @@ #include "../defines.h" -#define TAG "ProtoPirateCatalog" +#define TAG "PPCatalog" #define PROTOPIRATE_CC1101_REG_MDMCFG2 0x12U #define PROTOPIRATE_CC1101_MOD_FORMAT_MASK 0x70U diff --git a/protopirate_app.c b/protopirate_app.c index 7373955..d1bce56 100644 --- a/protopirate_app.c +++ b/protopirate_app.c @@ -10,18 +10,21 @@ #include "helpers/protopirate_radio.h" #include -#define TAG "ProtoPirateApp" +#define TAG "PPApp" // ----------------------------------------------------------------------------- // Plugin load / unload // ----------------------------------------------------------------------------- -void config_or_saved_plugin_unload(ProtoPirateApp* app, bool unload_config) { +void shared_plugin_unload(ProtoPirateApp* app, ProtoPirateSharedPlugin plugin_type) { furi_check(app); - if(unload_config) + if(plugin_type == ProtoPirateSharedPluginsConfig) { app->config_plugin = NULL; - else + } else if(plugin_type == ProtoPirateSharedPluginsSavedInfo) { app->saved_info_plugin = NULL; + } else if(plugin_type == ProtoPirateSharedPluginsAbout) { + app->about_plugin = NULL; + } if(app->plugin_manager) { plugin_manager_free(app->plugin_manager); @@ -34,17 +37,19 @@ void config_or_saved_plugin_unload(ProtoPirateApp* app, bool unload_config) { } } -bool config_or_saved_plugin_load(ProtoPirateApp* app, bool load_config) { +bool shared_plugin_load(ProtoPirateApp* app, ProtoPirateSharedPlugin plugin_type) { furi_check(app); - if(load_config) { + if(plugin_type == ProtoPirateSharedPluginsConfig) { if(app->config_plugin) return true; - } else { + } else if(plugin_type == ProtoPirateSharedPluginsSavedInfo) { if(app->saved_info_plugin) return true; + } else if(plugin_type == ProtoPirateSharedPluginsAbout) { + if(app->about_plugin) return true; } if(app->plugin_manager || app->plugin_resolver) { - config_or_saved_plugin_unload(app, load_config); + shared_plugin_unload(app, plugin_type); } CompositeApiResolver* resolver = composite_api_resolver_alloc(); @@ -54,27 +59,41 @@ bool config_or_saved_plugin_load(ProtoPirateApp* app, bool load_config) { } composite_api_resolver_add(resolver, firmware_api_interface); - PluginManager* manager = plugin_manager_alloc( - (load_config) ? PROTOPIRATE_CONFIG_PLUGIN_APP_ID : PROTOPIRATE_SAVED_INFO_PLUGIN_APP_ID, - (load_config) ? PROTOPIRATE_CONFIG_PLUGIN_API_VERSION : - PROTOPIRATE_SAVED_INFO_PLUGIN_API_VERSION, - composite_api_resolver_get(resolver)); + //Get the APPID and API VERSION for the Plugin we are loading. + const char* application_id = NULL; + const char* plugin_path = NULL; + uint32_t api_version = 0; + if(plugin_type == ProtoPirateSharedPluginsConfig) { + application_id = PROTOPIRATE_CONFIG_PLUGIN_APP_ID; + api_version = PROTOPIRATE_CONFIG_PLUGIN_API_VERSION; + plugin_path = CONFIG_PLUGIN_PATH; + } else if(plugin_type == ProtoPirateSharedPluginsSavedInfo) { + application_id = PROTOPIRATE_SAVED_INFO_PLUGIN_APP_ID; + api_version = PROTOPIRATE_SAVED_INFO_PLUGIN_API_VERSION; + plugin_path = SAVED_INFO_PLUGIN_PATH; + } else if(plugin_type == ProtoPirateSharedPluginsAbout) { + application_id = PROTOPIRATE_ABOUT_PLUGIN_APP_ID; + api_version = PROTOPIRATE_ABOUT_PLUGIN_API_VERSION; + plugin_path = ABOUT_PLUGIN_PATH; + } + + PluginManager* manager = + plugin_manager_alloc(application_id, api_version, composite_api_resolver_get(resolver)); if(!manager) { FURI_LOG_E(TAG, "Failed to allocate plugin manager"); composite_api_resolver_free(resolver); return false; } - PluginManagerError error = plugin_manager_load_single( - manager, (load_config) ? CONFIG_PLUGIN_PATH : SAVED_INFO_PLUGIN_PATH); + PluginManagerError error = plugin_manager_load_single(manager, plugin_path); if(error != PluginManagerErrorNone) { - FURI_LOG_E(TAG, "Failed to load config plugin %s: %d", CONFIG_PLUGIN_PATH, (int)error); + FURI_LOG_E(TAG, "Failed to load plugin %s: %d", plugin_path, (int)error); plugin_manager_free(manager); composite_api_resolver_free(resolver); return false; } - if(load_config) { + if(plugin_type == ProtoPirateSharedPluginsConfig) { const ProtoPirateConfigPlugin* plugin_config = plugin_manager_get_ep(manager, 0U); if(!plugin_config || !plugin_config->on_enter) { FURI_LOG_E(TAG, "Config plugin entry point is invalid"); @@ -83,7 +102,7 @@ bool config_or_saved_plugin_load(ProtoPirateApp* app, bool load_config) { return false; } app->config_plugin = plugin_config; - } else { + } else if(plugin_type == ProtoPirateSharedPluginsSavedInfo) { const ProtoPirateSavedInfoPlugin* plugin_saved_info = plugin_manager_get_ep(manager, 0U); if(!plugin_saved_info || !plugin_saved_info->on_enter) { FURI_LOG_E(TAG, "Saved Info plugin entry point is invalid"); @@ -92,7 +111,16 @@ bool config_or_saved_plugin_load(ProtoPirateApp* app, bool load_config) { return false; } app->saved_info_plugin = plugin_saved_info; - }; + } else if(plugin_type == ProtoPirateSharedPluginsAbout) { + const ProtoPirateAboutPlugin* plugin_about = plugin_manager_get_ep(manager, 0U); + if(!plugin_about || !plugin_about->on_enter) { + FURI_LOG_E(TAG, "About plugin entry point is invalid"); + plugin_manager_free(manager); + composite_api_resolver_free(resolver); + return false; + } + app->about_plugin = plugin_about; + } app->plugin_resolver = resolver; app->plugin_manager = manager; @@ -160,7 +188,6 @@ ProtoPirateApp* protopirate_app_alloc() { app->view_dispatcher, ProtoPirateViewSubmenu, submenu_get_view(app->submenu)); app->save_protocol = NULL; - app->save_from_saved_info = false; app->save_history_idx = 0; app->emulate_disabled_for_loaded = false; memset(app->save_filename, 0, sizeof(app->save_filename)); @@ -242,8 +269,13 @@ ProtoPirateApp* protopirate_app_alloc() { settings.auto_save, settings.hopping_enabled); - config_or_saved_plugin_load(app, true); - app->car_models_count = app->config_plugin->car_model_get_count(); + //Load the models database, get the count of the models for the list. + if(shared_plugin_load(app, ProtoPirateSharedPluginsConfig) && app->config_plugin) { + app->car_models_count = app->config_plugin->car_model_get_count(); + } else { + notification_message(app->notifications, &sequence_error); + app->car_models_count = 0; + } app->selected_model = malloc(sizeof(ProtoPirateCarModel)); app->selected_model->name = furi_string_alloc(); app->selected_model->preset = NULL; // important initialization @@ -251,24 +283,35 @@ ProtoPirateApp* protopirate_app_alloc() { app->variable_item_list = NULL; //Grab selected car model. - if(settings.car_model_index) { - app->config_plugin->car_model_get_by_index( - app->selected_model, settings.car_model_index, app->car_models_count, app->setting); - app->selected_model->last_preset_index = settings.preset_index; + if(app->config_plugin) { + if(settings.car_model_index) { + //Get the selected car model. + app->config_plugin->car_model_get_by_index( + app->selected_model, settings.car_model_index, app->car_models_count, app->setting); + app->selected_model->last_preset_index = settings.preset_index; - protopirate_preset_init( - app, - furi_string_get_cstr(app->selected_model->preset->name), - app->selected_model->preset->frequency, - app->selected_model->preset->data, - app->selected_model->preset->data_size); + //Preset for the selected model... + protopirate_preset_init( + app, + furi_string_get_cstr(app->selected_model->preset->name), + app->selected_model->preset->frequency, + app->selected_model->preset->data, + app->selected_model->preset->data_size); + } else { + //This will return Select a model or No Models in Database + app->config_plugin->car_model_get_by_index( + app->selected_model, 0, app->car_models_count, app->setting); + + //Preset set in Config. + protopirate_preset_init(app, preset_name, frequency, preset_data, preset_data_size); + } + + //Kill the config plugin now. + shared_plugin_unload(app, ProtoPirateSharedPluginsConfig); } else { - app->config_plugin->car_model_get_by_index( - app->selected_model, 0, app->car_models_count, app->setting); - + //Preset set in Config. protopirate_preset_init(app, preset_name, frequency, preset_data, preset_data_size); } - config_or_saved_plugin_unload(app, true); // Apply hopping state from settings app->txrx->hopper_state = settings.hopping_enabled ? ProtoPirateHopperStateRunning : diff --git a/protopirate_app_i.h b/protopirate_app_i.h index 5d02d0c..8670bfa 100644 --- a/protopirate_app_i.h +++ b/protopirate_app_i.h @@ -34,6 +34,7 @@ #endif #include "scenes/plugins/protopirate_config_plugin.h" #include "scenes/plugins/protopirate_saved_info_plugin.h" +#include "scenes/plugins/protopirate_about_plugin.h" #include "scenes/plugins/protopirate_psa_bf_plugin.h" #include "scenes/plugins/protopirate_tool_scene_plugin.h" #include "helpers/protopirate_views.h" @@ -44,8 +45,9 @@ #include #include "helpers/protopirate_settings.h" -#define CONFIG_PLUGIN_PATH APP_ASSETS_PATH("plugins/protopirate_config_plugin.fal") -#define SAVED_INFO_PLUGIN_PATH APP_ASSETS_PATH("plugins/protopirate_saved_info_plugin.fal") +#define CONFIG_PLUGIN_PATH APP_ASSETS_PATH("plugins/pp_config.fal") +#define SAVED_INFO_PLUGIN_PATH APP_ASSETS_PATH("plugins/pp_saved_info.fal") +#define ABOUT_PLUGIN_PATH APP_ASSETS_PATH("plugins/pp_about.fal") #define PROTOPIRATE_KEYSTORE_DIR_NAME APP_ASSETS_PATH("encrypted") @@ -89,20 +91,19 @@ struct ProtoPirateApp { SubGhzSetting* setting; ProtoPirateLock lock; FuriString* loaded_file_path; - bool deferred_storage_in_progress; - bool auto_save; - bool check_saved; - bool sound; - bool datetime_filenames; - bool radio_initialized; + uint8_t deferred_storage_in_progress : 1; + uint8_t auto_save : 1; + uint8_t check_saved : 1; + uint8_t sound : 1; + uint8_t datetime_filenames : 1; + uint8_t radio_initialized : 1; + uint8_t emulate_disabled_for_loaded : 1; + uint8_t emulate_feature_enabled : 1; uint32_t start_tx_time; uint8_t tx_power; char save_filename[64]; FuriString* save_protocol; uint16_t save_history_idx; - bool save_from_saved_info; - bool emulate_disabled_for_loaded; - bool emulate_feature_enabled; CompositeApiResolver* plugin_resolver; PluginManager* plugin_manager; #ifdef ENABLE_EMULATE_FEATURE @@ -114,6 +115,7 @@ struct ProtoPirateApp { #endif const ProtoPirateConfigPlugin* config_plugin; const ProtoPirateSavedInfoPlugin* saved_info_plugin; + const ProtoPirateAboutPlugin* about_plugin; CompositeApiResolver* psa_bf_plugin_resolver; PluginManager* psa_bf_plugin_manager; const ProtoPiratePsaBfPlugin* psa_bf_plugin; @@ -129,7 +131,7 @@ struct ProtoPirateApp { uint32_t tool_scene_nav_target; ProtoPirateCarModel* selected_model; - uint32_t car_models_count; + uint16_t car_models_count; }; #ifdef ENABLE_EMULATE_FEATURE @@ -146,8 +148,14 @@ bool protopirate_tool_scene_on_event(void* app, SceneManagerEvent event); void protopirate_tool_scene_on_exit(void* app); void protopirate_tool_scene_plugin_release(ProtoPirateApp* app); -bool config_or_saved_plugin_load(ProtoPirateApp* app, bool load_config); -void config_or_saved_plugin_unload(ProtoPirateApp* app, bool unload_config); +typedef enum ProtoPirateSharedPlugin { + ProtoPirateSharedPluginsConfig, + ProtoPirateSharedPluginsSavedInfo, + ProtoPirateSharedPluginsAbout, +} ProtoPirateSharedPlugin; + +bool shared_plugin_load(ProtoPirateApp* app, ProtoPirateSharedPlugin plugin_type); +void shared_plugin_unload(ProtoPirateApp* app, ProtoPirateSharedPlugin plugin_type); void protopirate_app_free(ProtoPirateApp* app); diff --git a/scenes/plugins/protopirate_about_plugin.c b/scenes/plugins/protopirate_about_plugin.c new file mode 100644 index 0000000..6f55c85 --- /dev/null +++ b/scenes/plugins/protopirate_about_plugin.c @@ -0,0 +1,310 @@ +#include "../../protopirate_app_i.h" +//#include "protopirate_about_plugin.h" +#include "pp_about_icons.h" + +static const ProtoPirateAboutSceneHostApi* g_about_scene_host_api = NULL; + +#define TAG "PPAboutPlugin" + +#define CREDITS_START_Y 28 +#define CREDITS_END_Y 52 +#define CREDIT_LINE_HEIGHT 10 +#define SCROLL_SPEED 1 + +#ifdef ENABLE_EMULATE_FEATURE +static const InputKey EMULATE_TOGGLE_COMBO[] = { + InputKeyUp, + InputKeyUp, + InputKeyDown, + InputKeyDown, + InputKeyLeft, + InputKeyRight, + InputKeyLeft, + InputKeyRight, +}; +#define EMULATE_TOGGLE_COMBO_LEN (sizeof(EMULATE_TOGGLE_COMBO) / sizeof(EMULATE_TOGGLE_COMBO[0])) +#endif + +static const char* credits[] = { + "", + "-=> App Development by <=-", + "RocketGod", + "MMX", + "Leeroy", + "gullradriel", + "Skorp's Weather App", + "Vadim's Radio Driver", + "", + "-=> Protocol Magic by <=-", + "L0rdDiakon", + "Leeroy", + "Li0ard", + "MMX", + "YougZ", + "DoobTheGoober", + "RocketGod", + "Skorp", + "Slackware", + "Trikk", + "Wootini", + "", + "-=> RE Support <=-", + "DoobTheGoober", + "Li0ard", + "MMX", + "NeedNotApply", + "RocketGod", + "Slackware", + "Trikk", + // can add more +}; + +#define CREDITS_COUNT (sizeof(credits) / sizeof(credits[0])) + +typedef struct { + uint8_t frame; + uint8_t seed; + int16_t scroll_offset; +#ifdef ENABLE_EMULATE_FEATURE + uint8_t combo_progress; +#endif +} GlitchState; + +static GlitchState g_state = {0}; + +static void draw_noise_pixels(Canvas* canvas, uint8_t density) { + for(uint8_t i = 0; i < density; i++) { + canvas_draw_dot(canvas, rand() % 128, rand() % 64); + } +} + +static void about_draw_callback(Canvas* canvas, void* context) { + UNUSED(context); + + srand(g_state.seed); + canvas_clear(canvas); + + // Light background static + canvas_set_color(canvas, ColorBlack); + draw_noise_pixels(canvas, 6 + (rand() % 6)); + + // Occasional subtle x-jitter + int8_t x_off = (rand() % 15 == 0) ? ((rand() % 4) - 2) : 0; + + // Animated TPP decoration (centered) + canvas_set_font(canvas, FontKeyboard); + if(g_state.frame % 8 < 4) { + canvas_draw_str_aligned( + canvas, 64, 18, AlignCenter, AlignBottom, ">>>=================<<<"); + } else { + canvas_draw_str_aligned( + canvas, 64, 18, AlignCenter, AlignBottom, ">>>======[TPP]======<<<"); + } + + // Draw credits region (clip area) + canvas_set_font(canvas, FontSecondary); + + // Calculate total scroll height + int16_t total_height = CREDITS_COUNT * CREDIT_LINE_HEIGHT; + + // Draw scrolling credits + for(size_t i = 0; i < CREDITS_COUNT; i++) { + int16_t y = CREDITS_START_Y + (i * CREDIT_LINE_HEIGHT) - g_state.scroll_offset; + + // Wrap around for endless scroll + while(y < CREDITS_START_Y - CREDIT_LINE_HEIGHT) { + y += total_height; + } + while(y > CREDITS_START_Y + total_height) { + y -= total_height; + } + + // Only draw if in visible region + if(y >= CREDITS_START_Y - CREDIT_LINE_HEIGHT && y <= CREDITS_END_Y) { + canvas_draw_str(canvas, x_off, y, credits[i]); + } + } + + // Draw fade/mask bars at top and bottom of credits area + canvas_set_color(canvas, ColorWhite); + canvas_draw_box(canvas, 0, 0, 128, CREDITS_START_Y - CREDIT_LINE_HEIGHT); + canvas_draw_box(canvas, 0, CREDITS_END_Y, 128, 14); + + // Redraw header over mask + canvas_set_color(canvas, ColorBlack); + canvas_set_font(canvas, FontPrimary); + canvas_draw_str(canvas, x_off, 10, "ProtoPirate v" FAP_VERSION); + + canvas_set_font(canvas, FontKeyboard); + if(g_state.frame % 8 < 4) { + canvas_draw_str_aligned( + canvas, 64, 18, AlignCenter, AlignBottom, ">>>=================<<<"); + } else { + canvas_draw_str_aligned( + canvas, 64, 18, AlignCenter, AlignBottom, ">>>======[TPP]======<<<"); + } + + // Redraw static in header area + srand(g_state.seed + 1); + for(uint8_t i = 0; i < 3; i++) { + canvas_draw_dot(canvas, rand() % 128, rand() % (CREDITS_START_Y - CREDIT_LINE_HEIGHT)); + } + + // Footer: The Pirate's Plunder Discord + canvas_set_font(canvas, FontKeyboard); + canvas_draw_str_aligned(canvas, 127, 62, AlignRight, AlignBottom, "discord.gg/thepirates"); + + // Rare subtle glitch bar + if(rand() % 30 == 0) { + canvas_set_color(canvas, ColorXOR); + uint8_t y = rand() % 60; + canvas_draw_box(canvas, 0, y, 128, 2); + } +} + +static bool about_input_callback(InputEvent* event, void* context) { + furi_check(context); +#ifdef ENABLE_EMULATE_FEATURE + ProtoPirateApp* app = context; + + if(event->type != InputTypePress) { + return false; + } + + if(event->key == InputKeyBack) { + return false; + } + + InputKey expected = EMULATE_TOGGLE_COMBO[g_state.combo_progress]; + if(event->key == expected) { + g_state.combo_progress++; + if(g_state.combo_progress >= EMULATE_TOGGLE_COMBO_LEN) { + g_state.combo_progress = 0; + view_dispatcher_send_custom_event( + app->view_dispatcher, ProtoPirateCustomEventAboutToggleEmulate); + } + } else if(event->key == EMULATE_TOGGLE_COMBO[0]) { + g_state.combo_progress = 1; + } else { + g_state.combo_progress = 0; + } + + return true; +#else + UNUSED(event); + return false; +#endif +} + +#ifdef ENABLE_EMULATE_FEATURE +static void about_show_emulate_toggle_popup(ProtoPirateApp* app) { + const bool now_enabled = app->emulate_feature_enabled; + + DialogMessage* message = dialog_message_alloc(); + dialog_message_set_buttons(message, NULL, "OK", NULL); + dialog_message_set_icon(message, &I_WarningDolphin_45x42, 0, 12); + dialog_message_set_header( + message, now_enabled ? "Emulate Unlocked" : "Emulate Locked", 64, 0, AlignCenter, AlignTop); + dialog_message_set_text( + message, + now_enabled ? "Transmission is\nnow enabled!" : "Transmission is\nnow disabled!", + 50, + 14, + AlignLeft, + AlignTop); + dialog_message_show(app->dialogs, message); + dialog_message_free(message); +} +#endif + +void plugin_protopirate_scene_about_on_enter(void* context) { + furi_check(context); + ProtoPirateApp* app = context; + + if(!g_about_scene_host_api->ensure_view_about(app)) { + notification_message(app->notifications, &sequence_error); + scene_manager_previous_scene(app->scene_manager); + return; + } + + g_state.frame = 0; + g_state.seed = furi_get_tick() & 0xFF; + g_state.scroll_offset = 0; +#ifdef ENABLE_EMULATE_FEATURE + g_state.combo_progress = 0; +#endif + + view_set_draw_callback(app->view_about, about_draw_callback); + view_set_input_callback(app->view_about, about_input_callback); + view_set_context(app->view_about, app); + + view_dispatcher_switch_to_view(app->view_dispatcher, ProtoPirateViewAbout); +} + +bool plugin_protopirate_scene_about_on_event(void* context, SceneManagerEvent event) { + ProtoPirateApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeTick) { + g_state.frame++; + + if(g_state.frame % 2 == 0) { + g_state.scroll_offset += SCROLL_SPEED; + int16_t total_height = CREDITS_COUNT * CREDIT_LINE_HEIGHT; + if(g_state.scroll_offset >= total_height) { + g_state.scroll_offset = 0; + } + } + + view_commit_model(app->view_about, true); + consumed = true; + } +#ifdef ENABLE_EMULATE_FEATURE + else if(event.type == SceneManagerEventTypeCustom) { + if(event.event == ProtoPirateCustomEventAboutToggleEmulate) { + //Toggle Emulate on + app->emulate_feature_enabled = !app->emulate_feature_enabled; + + ProtoPirateSettings settings; + g_about_scene_host_api->settings_load(&settings); + + settings.emulate_feature_enabled = app->emulate_feature_enabled; + g_about_scene_host_api->settings_save(&settings); + + notification_message( + app->notifications, + app->emulate_feature_enabled ? &sequence_success : &sequence_semi_success); + + about_show_emulate_toggle_popup(app); + consumed = true; + } + } +#endif + return consumed; +} + +void plugin_protopirate_scene_about_on_exit(void* context) { + UNUSED(context); +} + +void about_plugin_set_host_api(const ProtoPirateAboutSceneHostApi* host_api) { + g_about_scene_host_api = host_api; +} + +static const ProtoPirateAboutPlugin protopirate_about_plugin = { + .plugin_name = "About", + .on_enter = plugin_protopirate_scene_about_on_enter, + .on_event = plugin_protopirate_scene_about_on_event, + .on_exit = plugin_protopirate_scene_about_on_exit, + .set_host_api = about_plugin_set_host_api, +}; + +static const FlipperAppPluginDescriptor protopirate_about_plugin_descriptor = { + .appid = PROTOPIRATE_ABOUT_PLUGIN_APP_ID, + .ep_api_version = PROTOPIRATE_ABOUT_PLUGIN_API_VERSION, + .entry_point = &protopirate_about_plugin, +}; + +const FlipperAppPluginDescriptor* protopirate_about_plugin_ep(void) { + return &protopirate_about_plugin_descriptor; +} diff --git a/scenes/plugins/protopirate_about_plugin.h b/scenes/plugins/protopirate_about_plugin.h new file mode 100644 index 0000000..faed15a --- /dev/null +++ b/scenes/plugins/protopirate_about_plugin.h @@ -0,0 +1,22 @@ +#pragma once +#include +#include "../../helpers/protopirate_settings.h" + +#define PROTOPIRATE_ABOUT_PLUGIN_APP_ID "pp_about" +#define PROTOPIRATE_ABOUT_PLUGIN_API_VERSION 1U + +typedef struct ProtoPirateApp ProtoPirateApp; + +typedef struct ProtoPirateAboutSceneHostApi { + bool (*ensure_view_about)(ProtoPirateApp* app); + void (*settings_load)(ProtoPirateSettings* settings); + void (*settings_save)(ProtoPirateSettings* settings); +} ProtoPirateAboutSceneHostApi; + +typedef struct ProtoPirateAboutPlugin { + const char* plugin_name; + void (*on_enter)(void* app); + void (*on_exit)(void* app); + bool (*on_event)(void* app, SceneManagerEvent event); + void (*set_host_api)(const ProtoPirateAboutSceneHostApi* host_api); +} ProtoPirateAboutPlugin; diff --git a/scenes/plugins/protopirate_config_plugin.c b/scenes/plugins/protopirate_config_plugin.c index 0764bb4..72c1282 100644 --- a/scenes/plugins/protopirate_config_plugin.c +++ b/scenes/plugins/protopirate_config_plugin.c @@ -490,7 +490,7 @@ void config_plugin_set_host_api(const ProtoPirateConfigSceneHostApi* host_api) { } static const ProtoPirateConfigPlugin protopirate_config_plugin = { - .plugin_name = "ProtoPirate Config", + .plugin_name = "Config", .car_model_get_by_index = car_model_get_by_index, .car_model_get_count = car_model_get_count, .on_enter = plugin_on_enter, diff --git a/scenes/plugins/protopirate_config_plugin.h b/scenes/plugins/protopirate_config_plugin.h index 578789e..6c792db 100644 --- a/scenes/plugins/protopirate_config_plugin.h +++ b/scenes/plugins/protopirate_config_plugin.h @@ -3,7 +3,7 @@ #include #include "helpers/variable_item_list.h" -#define PROTOPIRATE_CONFIG_PLUGIN_APP_ID "protopirate_config_plugin" +#define PROTOPIRATE_CONFIG_PLUGIN_APP_ID "pp_config" #define PROTOPIRATE_CONFIG_PLUGIN_API_VERSION 2U enum ProtoPirateSettingIndex { diff --git a/scenes/plugins/protopirate_emulate_plugin.c b/scenes/plugins/protopirate_emulate_plugin.c index 60aec73..ca329b1 100644 --- a/scenes/plugins/protopirate_emulate_plugin.c +++ b/scenes/plugins/protopirate_emulate_plugin.c @@ -31,7 +31,7 @@ #include #include -#define TAG "ProtoPirateEmulatePlugin" +#define TAG "PPEmulatePlugin" #define MIN_TX_TIME 666U #define MIN_TX_TIME_KIA_V3_V4 1600U @@ -1571,7 +1571,7 @@ static void plugin_set_host_api(const ProtoPirateEmulateHostApi* host_api) { } static const ProtoPirateEmulatePlugin protopirate_emulate_plugin = { - .plugin_name = "ProtoPirate Emulate", + .plugin_name = "Emulate", .set_host_api = plugin_set_host_api, .on_enter = plugin_on_enter, .on_event = plugin_on_event, diff --git a/scenes/plugins/protopirate_emulate_plugin.h b/scenes/plugins/protopirate_emulate_plugin.h index e93efa3..a5d4309 100644 --- a/scenes/plugins/protopirate_emulate_plugin.h +++ b/scenes/plugins/protopirate_emulate_plugin.h @@ -6,7 +6,7 @@ #include #include -#define PROTOPIRATE_EMULATE_PLUGIN_APP_ID "protopirate_emulate_plugin" +#define PROTOPIRATE_EMULATE_PLUGIN_APP_ID "pp_emulate" #define PROTOPIRATE_EMULATE_PLUGIN_API_VERSION 2U typedef struct { diff --git a/scenes/plugins/protopirate_psa_bf_plugin.c b/scenes/plugins/protopirate_psa_bf_plugin.c index 42a9dbb..98a9fa1 100644 --- a/scenes/plugins/protopirate_psa_bf_plugin.c +++ b/scenes/plugins/protopirate_psa_bf_plugin.c @@ -9,7 +9,7 @@ #include #include #ifdef PROTOPIRATE_PSA_BF_PLUGIN_BUILD -#include "protopirate_psa_bf_plugin_icons.h" +#include "pp_bf_icons.h" #else #include "proto_pirate_icons.h" #endif @@ -521,7 +521,7 @@ static void plugin_set_host_api(const ProtoPiratePsaBfHostApi* api) { } static const ProtoPiratePsaBfPlugin protopirate_psa_bf_plugin = { - .plugin_name = "ProtoPirate PSA BF", + .plugin_name = "BF", .set_host_api = plugin_set_host_api, .needs_bruteforce = plugin_needs_bruteforce, .is_running = plugin_is_running, diff --git a/scenes/plugins/protopirate_psa_bf_plugin.h b/scenes/plugins/protopirate_psa_bf_plugin.h index 1ace292..e8ae1e9 100644 --- a/scenes/plugins/protopirate_psa_bf_plugin.h +++ b/scenes/plugins/protopirate_psa_bf_plugin.h @@ -8,7 +8,7 @@ #include "../../protocols/psa_bf_types.h" -#define PROTOPIRATE_PSA_BF_PLUGIN_APP_ID "protopirate_psa_bf_plugin" +#define PROTOPIRATE_PSA_BF_PLUGIN_APP_ID "pp_bf" #define PROTOPIRATE_PSA_BF_PLUGIN_API_VERSION 2U typedef struct ProtoPirateApp ProtoPirateApp; diff --git a/scenes/plugins/protopirate_saved_info_plugin.c b/scenes/plugins/protopirate_saved_info_plugin.c index abe24c6..d0a0ec1 100644 --- a/scenes/plugins/protopirate_saved_info_plugin.c +++ b/scenes/plugins/protopirate_saved_info_plugin.c @@ -3,11 +3,11 @@ #include "../../helpers/protopirate_storage.h" #include "../../protocols/protocols_common.h" #include "../../protocols/protocol_items.h" -#include "protopirate_saved_info_plugin_icons.h" +#include "pp_saved_info_icons.h" static const ProtoPirateSavedInfoSceneHostApi* g_saved_info_scene_host_api = NULL; -#define TAG "ProtoPirateSavedInfoPlugin" +#define TAG "PPSavedInfoPlugin" #define STATE_EMULATE 0 #define STATE_BF 1 @@ -359,7 +359,7 @@ void saved_info_plugin_set_host_api(const ProtoPirateSavedInfoSceneHostApi* host } static const ProtoPirateSavedInfoPlugin protopirate_saved_info_plugin = { - .plugin_name = "ProtoPirate Saved Info", + .plugin_name = "Saved", .on_enter = plugin_protopirate_scene_saved_info_on_enter, .on_event = plugin_protopirate_scene_saved_info_on_event, .on_exit = plugin_protopirate_scene_saved_info_on_exit, diff --git a/scenes/plugins/protopirate_saved_info_plugin.h b/scenes/plugins/protopirate_saved_info_plugin.h index 4a115c1..a7bfe47 100644 --- a/scenes/plugins/protopirate_saved_info_plugin.h +++ b/scenes/plugins/protopirate_saved_info_plugin.h @@ -1,7 +1,7 @@ #pragma once #include -#define PROTOPIRATE_SAVED_INFO_PLUGIN_APP_ID "protopirate_saved_info_plugin" +#define PROTOPIRATE_SAVED_INFO_PLUGIN_APP_ID "pp_saved_info" #define PROTOPIRATE_SAVED_INFO_PLUGIN_API_VERSION 1U typedef struct ProtoPirateApp ProtoPirateApp; diff --git a/scenes/protopirate_scene_about.c b/scenes/protopirate_scene_about.c index 469fa0f..b9cb921 100644 --- a/scenes/protopirate_scene_about.c +++ b/scenes/protopirate_scene_about.c @@ -1,292 +1,43 @@ // scenes/protopirate_scene_about.c #include "../protopirate_app_i.h" #include "../helpers/protopirate_settings.h" -#include "proto_pirate_icons.h" -#include -#include -#include -#include -#define CREDITS_START_Y 28 -#define CREDITS_END_Y 52 -#define CREDIT_LINE_HEIGHT 10 -#define SCROLL_SPEED 1 - -#ifdef ENABLE_EMULATE_FEATURE -static const InputKey EMULATE_TOGGLE_COMBO[] = { - InputKeyUp, - InputKeyUp, - InputKeyDown, - InputKeyDown, - InputKeyLeft, - InputKeyRight, - InputKeyLeft, - InputKeyRight, +static const ProtoPirateAboutSceneHostApi protopirate_about_scene_host_api = { + .ensure_view_about = protopirate_ensure_view_about, + .settings_load = protopirate_settings_load, + .settings_save = protopirate_settings_save, }; -#define EMULATE_TOGGLE_COMBO_LEN (sizeof(EMULATE_TOGGLE_COMBO) / sizeof(EMULATE_TOGGLE_COMBO[0])) -#endif - -static const char* credits[] = { - "", - "-=> App Development by", - "RocketGod", - "MMX", - "Leeroy", - "gullradriel", - "Skorp's Weather App", - "Vadim's Radio Driver", - "-=> Protocol Magic by", - "L0rdDiakon", - "Leeroy", - "Li0ard", - "MMX", - "YougZ", - "DoobTheGoober", - "RocketGod", - "Skorp", - "Slackware", - "Trikk", - "Wootini", - "-=> RE Support", - "DoobTheGoober", - "Li0ard", - "MMX", - "NeedNotApply", - "RocketGod", - "Slackware", - "Trikk", - // can add more -}; - -#define CREDITS_COUNT (sizeof(credits) / sizeof(credits[0])) - -typedef struct { - uint8_t frame; - uint8_t seed; - int16_t scroll_offset; -#ifdef ENABLE_EMULATE_FEATURE - uint8_t combo_progress; -#endif -} GlitchState; - -static GlitchState g_state = {0}; - -static void draw_noise_pixels(Canvas* canvas, uint8_t density) { - for(uint8_t i = 0; i < density; i++) { - canvas_draw_dot(canvas, rand() % 128, rand() % 64); - } -} - -static void about_draw_callback(Canvas* canvas, void* context) { - UNUSED(context); - - srand(g_state.seed); - canvas_clear(canvas); - - // Light background static - canvas_set_color(canvas, ColorBlack); - draw_noise_pixels(canvas, 6 + (rand() % 6)); - - // Occasional subtle x-jitter - int8_t x_off = (rand() % 15 == 0) ? ((rand() % 4) - 2) : 0; - - // Animated TPP decoration (centered) - canvas_set_font(canvas, FontKeyboard); - if(g_state.frame % 8 < 4) { - canvas_draw_str_aligned( - canvas, 64, 18, AlignCenter, AlignBottom, ">>>=================<<<"); - } else { - canvas_draw_str_aligned( - canvas, 64, 18, AlignCenter, AlignBottom, ">>>======[TPP]======<<<"); - } - - // Draw credits region (clip area) - canvas_set_font(canvas, FontSecondary); - - // Calculate total scroll height - int16_t total_height = CREDITS_COUNT * CREDIT_LINE_HEIGHT; - - // Draw scrolling credits - for(size_t i = 0; i < CREDITS_COUNT; i++) { - int16_t y = CREDITS_START_Y + (i * CREDIT_LINE_HEIGHT) - g_state.scroll_offset; - - // Wrap around for endless scroll - while(y < CREDITS_START_Y - CREDIT_LINE_HEIGHT) { - y += total_height; - } - while(y > CREDITS_START_Y + total_height) { - y -= total_height; - } - - // Only draw if in visible region - if(y >= CREDITS_START_Y - CREDIT_LINE_HEIGHT && y <= CREDITS_END_Y) { - canvas_draw_str(canvas, x_off, y, credits[i]); - } - } - - // Draw fade/mask bars at top and bottom of credits area - canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, 0, 0, 128, CREDITS_START_Y - CREDIT_LINE_HEIGHT); - canvas_draw_box(canvas, 0, CREDITS_END_Y, 128, 14); - - // Redraw header over mask - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, x_off, 10, "ProtoPirate v" FAP_VERSION); - - canvas_set_font(canvas, FontKeyboard); - if(g_state.frame % 8 < 4) { - canvas_draw_str_aligned( - canvas, 64, 18, AlignCenter, AlignBottom, ">>>=================<<<"); - } else { - canvas_draw_str_aligned( - canvas, 64, 18, AlignCenter, AlignBottom, ">>>======[TPP]======<<<"); - } - - // Redraw static in header area - srand(g_state.seed + 1); - for(uint8_t i = 0; i < 3; i++) { - canvas_draw_dot(canvas, rand() % 128, rand() % (CREDITS_START_Y - CREDIT_LINE_HEIGHT)); - } - - // Footer: The Pirate's Plunder Discord - canvas_set_font(canvas, FontKeyboard); - canvas_draw_str_aligned(canvas, 127, 62, AlignRight, AlignBottom, "discord.gg/thepirates"); - - // Rare subtle glitch bar - if(rand() % 30 == 0) { - canvas_set_color(canvas, ColorXOR); - uint8_t y = rand() % 60; - canvas_draw_box(canvas, 0, y, 128, 2); - } -} - -static bool about_input_callback(InputEvent* event, void* context) { - furi_check(context); -#ifdef ENABLE_EMULATE_FEATURE - ProtoPirateApp* app = context; - - if(event->type != InputTypePress) { - return false; - } - - if(event->key == InputKeyBack) { - return false; - } - - InputKey expected = EMULATE_TOGGLE_COMBO[g_state.combo_progress]; - if(event->key == expected) { - g_state.combo_progress++; - if(g_state.combo_progress >= EMULATE_TOGGLE_COMBO_LEN) { - g_state.combo_progress = 0; - view_dispatcher_send_custom_event( - app->view_dispatcher, ProtoPirateCustomEventAboutToggleEmulate); - } - } else if(event->key == EMULATE_TOGGLE_COMBO[0]) { - g_state.combo_progress = 1; - } else { - g_state.combo_progress = 0; - } - - return true; -#else - UNUSED(event); - return false; -#endif -} - -#ifdef ENABLE_EMULATE_FEATURE -static void about_show_emulate_toggle_popup(ProtoPirateApp* app) { - const bool now_enabled = app->emulate_feature_enabled; - - DialogMessage* message = dialog_message_alloc(); - dialog_message_set_buttons(message, NULL, "OK", NULL); - dialog_message_set_icon(message, &I_WarningDolphin_45x42, 0, 12); - dialog_message_set_header( - message, now_enabled ? "Emulate Unlocked" : "Emulate Locked", 64, 0, AlignCenter, AlignTop); - dialog_message_set_text( - message, - now_enabled ? "Transmission is\nnow enabled!" : "Transmission is\nnow disabled!", - 50, - 14, - AlignLeft, - AlignTop); - dialog_message_show(app->dialogs, message); - dialog_message_free(message); -} -#endif void protopirate_scene_about_on_enter(void* context) { - furi_check(context); ProtoPirateApp* app = context; - if(!protopirate_ensure_view_about(app)) { + if(!shared_plugin_load(app, ProtoPirateSharedPluginsAbout)) { notification_message(app->notifications, &sequence_error); scene_manager_previous_scene(app->scene_manager); return; } - g_state.frame = 0; - g_state.seed = furi_get_tick() & 0xFF; - g_state.scroll_offset = 0; -#ifdef ENABLE_EMULATE_FEATURE - g_state.combo_progress = 0; -#endif - - view_set_draw_callback(app->view_about, about_draw_callback); - view_set_input_callback(app->view_about, about_input_callback); - view_set_context(app->view_about, app); - - view_dispatcher_switch_to_view(app->view_dispatcher, ProtoPirateViewAbout); + app->about_plugin->set_host_api(&protopirate_about_scene_host_api); + app->about_plugin->on_enter(app); } bool protopirate_scene_about_on_event(void* context, SceneManagerEvent event) { - ProtoPirateApp* app = context; - bool consumed = false; + ProtoPirateApp* app = (ProtoPirateApp*)context; - if(event.type == SceneManagerEventTypeTick) { - g_state.frame++; - g_state.seed = rand(); - - if(g_state.frame % 2 == 0) { - g_state.scroll_offset += SCROLL_SPEED; - int16_t total_height = CREDITS_COUNT * CREDIT_LINE_HEIGHT; - if(g_state.scroll_offset >= total_height) { - g_state.scroll_offset = 0; - } - } - - view_commit_model(app->view_about, true); - consumed = true; + //I can't set the next scene from inside the plugin, or it causes crazy crashes. + if(event.type == SceneManagerEventTypeBack) { + scene_manager_previous_scene(app->scene_manager); + return true; } -#ifdef ENABLE_EMULATE_FEATURE - else if(event.type == SceneManagerEventTypeCustom) { - if(event.event == ProtoPirateCustomEventAboutToggleEmulate) { - app->emulate_feature_enabled = !app->emulate_feature_enabled; - ProtoPirateSettings settings; - protopirate_settings_load(&settings); - settings.emulate_feature_enabled = app->emulate_feature_enabled; - protopirate_settings_save(&settings); - - notification_message( - app->notifications, - app->emulate_feature_enabled ? &sequence_success : &sequence_semi_success); - - about_show_emulate_toggle_popup(app); - consumed = true; - } - } -#endif - - return consumed; + //Handle About event in plugin. + return app->about_plugin->on_event(app, event); } void protopirate_scene_about_on_exit(void* context) { - furi_check(context); ProtoPirateApp* app = context; - view_set_draw_callback(app->view_about, NULL); view_set_input_callback(app->view_about, NULL); view_set_context(app->view_about, NULL); + shared_plugin_unload(app, ProtoPirateSharedPluginsAbout); } diff --git a/scenes/protopirate_scene_emulate.c b/scenes/protopirate_scene_emulate.c index eb7e7e8..6493e98 100644 --- a/scenes/protopirate_scene_emulate.c +++ b/scenes/protopirate_scene_emulate.c @@ -11,9 +11,9 @@ #include #include -#define TAG "ProtoPirateSceneEmulate" +#define TAG "PPSceneEmulate" -#define EMULATE_PLUGIN_PATH APP_ASSETS_PATH("plugins/protopirate_emulate_plugin.fal") +#define EMULATE_PLUGIN_PATH APP_ASSETS_PATH("plugins/pp_emulate.fal") static bool host_radio_init(void* app) { return protopirate_radio_init((ProtoPirateApp*)app); diff --git a/scenes/protopirate_scene_need_saving.c b/scenes/protopirate_scene_need_saving.c index 02e3b0a..526d1cc 100644 --- a/scenes/protopirate_scene_need_saving.c +++ b/scenes/protopirate_scene_need_saving.c @@ -2,7 +2,7 @@ #include "../protopirate_app_i.h" #include "proto_pirate_icons.h" -#define TAG "ProtoPirateNeedSaving" +#define TAG "PPNeedSaving" static void protopirate_scene_need_saving_callback(GuiButtonType result, InputType type, void* context) { diff --git a/scenes/protopirate_scene_receiver.c b/scenes/protopirate_scene_receiver.c index 1246499..ee04617 100644 --- a/scenes/protopirate_scene_receiver.c +++ b/scenes/protopirate_scene_receiver.c @@ -7,7 +7,7 @@ #include #include "proto_pirate_icons.h" -#define TAG "ProtoPirateSceneRx" +#define TAG "PPSceneRx" #define DEFERRED_STORAGE_TIME 1000 diff --git a/scenes/protopirate_scene_receiver_config.c b/scenes/protopirate_scene_receiver_config.c index ef3582f..82e553f 100644 --- a/scenes/protopirate_scene_receiver_config.c +++ b/scenes/protopirate_scene_receiver_config.c @@ -11,7 +11,7 @@ static const ProtoPirateConfigSceneHostApi protopirate_config_scene_host_api = { void protopirate_scene_receiver_config_on_enter(void* context) { ProtoPirateApp* app = context; - if(!config_or_saved_plugin_load(app, true)) { + if(!shared_plugin_load(app, ProtoPirateSharedPluginsConfig)) { notification_message(app->notifications, &sequence_error); scene_manager_previous_scene(app->scene_manager); return; @@ -37,5 +37,5 @@ bool protopirate_scene_receiver_config_on_event(void* context, SceneManagerEvent void protopirate_scene_receiver_config_on_exit(void* context) { ProtoPirateApp* app = context; - config_or_saved_plugin_unload(app, true); + shared_plugin_unload(app, ProtoPirateSharedPluginsConfig); } diff --git a/scenes/protopirate_scene_receiver_info.c b/scenes/protopirate_scene_receiver_info.c index 9b1516c..8626eb5 100644 --- a/scenes/protopirate_scene_receiver_info.c +++ b/scenes/protopirate_scene_receiver_info.c @@ -6,7 +6,7 @@ #include "proto_pirate_icons.h" #include -#define TAG "ProtoPirateReceiverInfo" +#define TAG "PPReceiverInfo" #define STATE_EMULATE 0 #define STATE_BF 1 @@ -329,7 +329,6 @@ bool protopirate_scene_receiver_info_on_event(void* context, SceneManagerEvent e if(app->save_protocol) furi_string_free(app->save_protocol); app->save_protocol = protocol; // transfer ownership app->save_history_idx = app->txrx->idx_menu_chosen; - app->save_from_saved_info = false; // Configure and show text input text_input_reset(app->text_input); diff --git a/scenes/protopirate_scene_saved.c b/scenes/protopirate_scene_saved.c index c1ac271..c86d70a 100644 --- a/scenes/protopirate_scene_saved.c +++ b/scenes/protopirate_scene_saved.c @@ -4,7 +4,7 @@ #include "proto_pirate_icons.h" -#define TAG "ProtoPirateSceneSaved" +#define TAG "PPSceneSaved" void protopirate_scene_saved_on_enter(void* context) { furi_check(context); @@ -34,7 +34,7 @@ void protopirate_scene_saved_on_enter(void* context) { } DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options(&browser_options, ".psf", &I_subghz_10px); + dialog_file_browser_set_basic_options(&browser_options, ".psf", &I_protopirate_10px); browser_options.base_path = PROTOPIRATE_APP_FOLDER; browser_options.skip_assets = true; browser_options.hide_dot_files = true; diff --git a/scenes/protopirate_scene_saved_info.c b/scenes/protopirate_scene_saved_info.c index 1066440..2c1cc03 100644 --- a/scenes/protopirate_scene_saved_info.c +++ b/scenes/protopirate_scene_saved_info.c @@ -16,7 +16,7 @@ static const ProtoPirateSavedInfoSceneHostApi protopirate_saved_info_scene_host_ void protopirate_scene_saved_info_on_enter(void* context) { ProtoPirateApp* app = context; - if(!config_or_saved_plugin_load(app, false)) { + if(!shared_plugin_load(app, ProtoPirateSharedPluginsSavedInfo)) { notification_message(app->notifications, &sequence_error); scene_manager_previous_scene(app->scene_manager); return; @@ -27,13 +27,14 @@ void protopirate_scene_saved_info_on_enter(void* context) { } bool protopirate_scene_saved_info_on_event(void* context, SceneManagerEvent event) { + ProtoPirateApp* app = ((ProtoPirateApp*)context); + //I can't set the next scene from inside the plugin, or it causes crazy crashes. if(event.type == SceneManagerEventTypeCustom) { if(event.event == ProtoPirateCustomEventSavedInfoEmulateDelayedStart) { //Start Emulate Scene. #ifdef ENABLE_EMULATE_FEATURE - scene_manager_next_scene( - ((ProtoPirateApp*)context)->scene_manager, ProtoPirateSceneEmulate); + scene_manager_next_scene(app->scene_manager, ProtoPirateSceneEmulate); return true; #endif } else if(event.event == ProtoPirateCustomEventSavedInfoExit) { @@ -43,12 +44,11 @@ bool protopirate_scene_saved_info_on_event(void* context, SceneManagerEvent even } //Handle Saved Info event in plugin. - return ((ProtoPirateApp*)context)->saved_info_plugin->on_event(context, event); + return app->saved_info_plugin->on_event(app, event); } void protopirate_scene_saved_info_on_exit(void* context) { ProtoPirateApp* app = context; - UNUSED(app); - config_or_saved_plugin_unload(app, false); + shared_plugin_unload(app, ProtoPirateSharedPluginsSavedInfo); } diff --git a/scenes/protopirate_scene_start.c b/scenes/protopirate_scene_start.c index 089724c..67c599e 100644 --- a/scenes/protopirate_scene_start.c +++ b/scenes/protopirate_scene_start.c @@ -4,7 +4,7 @@ #include "proto_pirate_icons.h" -#define TAG "ProtoPirateSceneStart" +#define TAG "PPSceneStart" typedef enum { SubmenuIndexProtoPirateReceiver, diff --git a/scenes/protopirate_scene_sub_decode.c b/scenes/protopirate_scene_sub_decode.c index cc7b76f..07dc86d 100644 --- a/scenes/protopirate_scene_sub_decode.c +++ b/scenes/protopirate_scene_sub_decode.c @@ -36,12 +36,12 @@ void protopirate_scene_sub_decode_on_exit(void* context) { #include #ifdef PROTOPIRATE_SUB_DECODE_PLUGIN_BUILD -#include "protopirate_sub_decode_plugin_icons.h" +#include "pp_sub_decode_icons.h" #else #include "proto_pirate_icons.h" #endif -#define TAG "ProtoPirateSubDecode" +#define TAG "PPSubDecode" static const ProtoPirateToolSceneHostApi* g_tool_scene_host_api = NULL; @@ -689,7 +689,6 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even // Store context for when text input confirms app->save_history_idx = app->txrx->idx_menu_chosen; - app->save_from_saved_info = false; //Make sure we have a text input window. app->text_input = text_input_alloc(); @@ -1468,7 +1467,7 @@ static void sub_decode_plugin_set_host_api(const ProtoPirateToolSceneHostApi* ho } static const ProtoPirateToolScenePlugin protopirate_sub_decode_plugin = { - .plugin_name = "ProtoPirate Sub Decode", + .plugin_name = "Sub Decode", .kind = ProtoPirateToolScenePluginKindSubDecode, .set_host_api = sub_decode_plugin_set_host_api, .on_enter = protopirate_scene_sub_decode_on_enter, diff --git a/scenes/protopirate_scene_timing_tuner.c b/scenes/protopirate_scene_timing_tuner.c index 8da432d..0281ade 100644 --- a/scenes/protopirate_scene_timing_tuner.c +++ b/scenes/protopirate_scene_timing_tuner.c @@ -23,7 +23,7 @@ void protopirate_scene_timing_tuner_on_exit(void* context) { #include #include -#define TAG "ProtoPirateTimingTuner" +#define TAG "PPTimingTuner" static const ProtoPirateToolSceneHostApi* g_tool_scene_host_api = NULL; @@ -808,7 +808,7 @@ static void timing_tuner_plugin_set_host_api(const ProtoPirateToolSceneHostApi* } static const ProtoPirateToolScenePlugin protopirate_timing_tuner_plugin = { - .plugin_name = "ProtoPirate Timing Tuner", + .plugin_name = "Timing Tuner", .kind = ProtoPirateToolScenePluginKindTimingTuner, .set_host_api = timing_tuner_plugin_set_host_api, .on_enter = protopirate_scene_timing_tuner_on_enter,