diff --git a/applications/external/mifare_fuzzer/application.fam b/applications/external/mifare_fuzzer/application.fam deleted file mode 100644 index 5d02b9235..000000000 --- a/applications/external/mifare_fuzzer/application.fam +++ /dev/null @@ -1,18 +0,0 @@ -App( - appid="mifare_fuzzer", - name="Mifare Fuzzer", - apptype=FlipperAppType.EXTERNAL, - entry_point="mifare_fuzzer_app", - requires=[ - "storage", - "gui", - ], - stack_size=4 * 1024, - fap_icon="images/mifare_fuzzer_10px.png", - fap_category="NFC", - fap_icon_assets="images", - fap_author="@spheeere98", - fap_weburl="https://github.com/spheeere98/mifare_fuzzer", - fap_version="1.0", - fap_description="App emulates Mifare Classic cards with various UIDs to check how reader reacts on them", -) diff --git a/applications/external/mifare_fuzzer/images/mifare_fuzzer_10px.png b/applications/external/mifare_fuzzer/images/mifare_fuzzer_10px.png deleted file mode 100644 index 6987cbf95..000000000 Binary files a/applications/external/mifare_fuzzer/images/mifare_fuzzer_10px.png and /dev/null differ diff --git a/applications/external/mifare_fuzzer/mifare_fuzzer.c b/applications/external/mifare_fuzzer/mifare_fuzzer.c deleted file mode 100644 index 76fec98ed..000000000 --- a/applications/external/mifare_fuzzer/mifare_fuzzer.c +++ /dev/null @@ -1,158 +0,0 @@ -#include "mifare_fuzzer_i.h" - -/// @brief mifare_fuzzer_custom_event_callback() -/// @param context -/// @param event -/// @return -static bool mifare_fuzzer_custom_event_callback(void* context, uint32_t event) { - furi_assert(context); - MifareFuzzerApp* app = context; - return scene_manager_handle_custom_event(app->scene_manager, event); -} - -/// @brief mifare_fuzzer_back_event_callback() -/// @param context -/// @return -static bool mifare_fuzzer_back_event_callback(void* context) { - furi_assert(context); - MifareFuzzerApp* app = context; - return scene_manager_handle_back_event(app->scene_manager); -} - -/// @brief mifare_fuzzer_tick_event_callback() -/// @param context -static void mifare_fuzzer_tick_event_callback(void* context) { - furi_assert(context); - MifareFuzzerApp* app = context; - scene_manager_handle_tick_event(app->scene_manager); -} - -/// @brief mifare_fuzzer_alloc() -/// @return -MifareFuzzerApp* mifare_fuzzer_alloc() { - MifareFuzzerApp* app = malloc(sizeof(MifareFuzzerApp)); - - app->view_dispatcher = view_dispatcher_alloc(); - app->scene_manager = scene_manager_alloc(&mifare_fuzzer_scene_handlers, app); - view_dispatcher_enable_queue(app->view_dispatcher); - view_dispatcher_set_event_callback_context(app->view_dispatcher, app); - view_dispatcher_set_custom_event_callback( - app->view_dispatcher, mifare_fuzzer_custom_event_callback); - view_dispatcher_set_navigation_event_callback( - app->view_dispatcher, mifare_fuzzer_back_event_callback); - - // 1000 ticks are about 1 sec - view_dispatcher_set_tick_event_callback( - app->view_dispatcher, mifare_fuzzer_tick_event_callback, MIFARE_FUZZER_TICK_PERIOD); - - // Open GUI record - app->gui = furi_record_open(RECORD_GUI); - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - - // view: select card type - app->submenu_card = submenu_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, MifareFuzzerViewSelectCard, submenu_get_view(app->submenu_card)); - - // view: select attack type - app->submenu_attack = submenu_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, MifareFuzzerViewSelectAttack, submenu_get_view(app->submenu_attack)); - - // view: emulator - app->emulator_view = mifare_fuzzer_emulator_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - MifareFuzzerViewEmulator, - mifare_fuzzer_emulator_get_view(app->emulator_view)); - - // worker - app->worker = mifare_fuzzer_worker_alloc(); - - // storage - app->storage = furi_record_open(RECORD_STORAGE); - if(!storage_simply_mkdir(app->storage, MIFARE_FUZZER_APP_FOLDER)) { - FURI_LOG_E(TAG, "Could not create folder: %s", MIFARE_FUZZER_APP_FOLDER); - } - - // dialog - app->dialogs = furi_record_open(RECORD_DIALOGS); - - // furi strings - app->uid_str = furi_string_alloc(); - app->file_path = furi_string_alloc(); - app->app_folder = furi_string_alloc_set(MIFARE_FUZZER_APP_FOLDER); - - return app; -} - -/// @brief mifare_fuzzer_free() -/// @param app -void mifare_fuzzer_free(MifareFuzzerApp* app) { - furi_assert(app); - - // Views - //FURI_LOG_D(TAG, "mifare_fuzzer_free() :: Views"); - view_dispatcher_remove_view(app->view_dispatcher, MifareFuzzerViewSelectCard); - view_dispatcher_remove_view(app->view_dispatcher, MifareFuzzerViewSelectAttack); - view_dispatcher_remove_view(app->view_dispatcher, MifareFuzzerViewEmulator); - - // Submenus - //FURI_LOG_D(TAG, "mifare_fuzzer_free() :: Submenus"); - submenu_free(app->submenu_card); - submenu_free(app->submenu_attack); - - // View Dispatcher - //FURI_LOG_D(TAG, "mifare_fuzzer_free() :: View Dispatcher"); - view_dispatcher_free(app->view_dispatcher); - - // Scene Manager - //FURI_LOG_D(TAG, "mifare_fuzzer_free() :: Scene Manager"); - scene_manager_free(app->scene_manager); - - // GUI - //FURI_LOG_D(TAG, "mifare_fuzzer_free() :: GUI"); - furi_record_close(RECORD_GUI); - app->gui = NULL; - - // Worker - //FURI_LOG_D(TAG, "mifare_fuzzer_free() :: Worker"); - mifare_fuzzer_worker_free(app->worker); - - // storage - furi_record_close(RECORD_STORAGE); - app->storage = NULL; - - // dialog - furi_record_close(RECORD_DIALOGS); - app->dialogs = NULL; - - // furi strings - furi_string_free(app->uid_str); - furi_string_free(app->file_path); - furi_string_free(app->app_folder); - - // App - //FURI_LOG_D(TAG, "mifare_fuzzer_free() :: App"); - free(app); -} - -/// @brief mifare_fuzzer_app (ENTRYPOINT) -/// @param p -/// @return -int32_t mifare_fuzzer_app(void* p) { - UNUSED(p); - //FURI_LOG_D(TAG, "mifare_fuzzer_app()"); - - MifareFuzzerApp* app = mifare_fuzzer_alloc(); - // init some defaults - scene_manager_set_scene_state(app->scene_manager, MifareFuzzerSceneStart, 0); - scene_manager_set_scene_state(app->scene_manager, MifareFuzzerSceneAttack, 0); - // open scene - scene_manager_next_scene(app->scene_manager, MifareFuzzerSceneStart); - view_dispatcher_run(app->view_dispatcher); - // free - mifare_fuzzer_free(app); - - return 0; -} diff --git a/applications/external/mifare_fuzzer/mifare_fuzzer.h b/applications/external/mifare_fuzzer/mifare_fuzzer.h deleted file mode 100644 index 42e123e5f..000000000 --- a/applications/external/mifare_fuzzer/mifare_fuzzer.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -typedef struct MifareFuzzerApp MifareFuzzerApp; diff --git a/applications/external/mifare_fuzzer/mifare_fuzzer_custom_events.h b/applications/external/mifare_fuzzer/mifare_fuzzer_custom_events.h deleted file mode 100644 index fc3fc28df..000000000 --- a/applications/external/mifare_fuzzer/mifare_fuzzer_custom_events.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -typedef enum MifareFuzzerEvent { - MifareFuzzerEventClassic1k = 1, - MifareFuzzerEventClassic4k, - MifareFuzzerEventUltralight, - MifareFuzzerEventTestValueAttack, - MifareFuzzerEventRandomValuesAttack, - MifareFuzzerEventLoadUIDsFromFileAttack, - MifareFuzzerEventStartAttack, - MifareFuzzerEventStopAttack, - MifareFuzzerEventIncrementTicks, - MifareFuzzerEventDecrementTicks, -} MifareFuzzerEvent; diff --git a/applications/external/mifare_fuzzer/mifare_fuzzer_i.h b/applications/external/mifare_fuzzer/mifare_fuzzer_i.h deleted file mode 100644 index ea58fa267..000000000 --- a/applications/external/mifare_fuzzer/mifare_fuzzer_i.h +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once - -#include -#include - -#include -#include -#include - -#include - -#include - -#include - -#include -//#include -//#include -#include - -#include "mifare_fuzzer.h" - -#include "scenes/mifare_fuzzer_scene.h" -#include "views/mifare_fuzzer_emulator.h" - -#include "mifare_fuzzer_worker.h" - -#define TAG "MifareFuzzerApp" - -#define MIFARE_FUZZER_APP_FOLDER EXT_PATH("mifare_fuzzer") -#define MIFARE_FUZZER_FILE_EXT ".txt" - -#define MIFARE_FUZZER_TICK_PERIOD 200 -#define MIFARE_FUZZER_DEFAULT_TICKS_BETWEEN_CARDS 10 -#define MIFARE_FUZZER_MIN_TICKS_BETWEEN_CARDS 5 -#define MIFARE_FUZZER_MAX_TICKS_BETWEEN_CARDS 50 - -typedef enum MifareFuzzerSceneState { - MifareFuzzerSceneStateClassic1k, - MifareFuzzerSceneStateClassic4k, - MifareFuzzerSceneStateUltralight, -} MifareFuzzerSceneState; - -typedef enum { - MifareFuzzerViewSelectCard, - MifareFuzzerViewSelectAttack, - MifareFuzzerViewEmulator, -} MifareFuzzerView; - -struct MifareFuzzerApp { - Gui* gui; - - ViewDispatcher* view_dispatcher; - - SceneManager* scene_manager; - - DialogsApp* dialogs; - - Storage* storage; - - // Common Views - Submenu* submenu_card; - Submenu* submenu_attack; - - MifareFuzzerEmulator* emulator_view; - - MifareFuzzerWorker* worker; - - MifareCard card; - MifareFuzzerAttack attack; - FuriHalNfcDevData nfc_dev_data; - FuriString* app_folder; - FuriString* file_path; - FuriString* uid_str; - Stream* uids_stream; -}; diff --git a/applications/external/mifare_fuzzer/mifare_fuzzer_worker.c b/applications/external/mifare_fuzzer/mifare_fuzzer_worker.c deleted file mode 100644 index ac48a1008..000000000 --- a/applications/external/mifare_fuzzer/mifare_fuzzer_worker.c +++ /dev/null @@ -1,87 +0,0 @@ - -#include "mifare_fuzzer_worker.h" - -/// @brief mifare_fuzzer_worker_alloc() -/// @return -MifareFuzzerWorker* mifare_fuzzer_worker_alloc() { - MifareFuzzerWorker* mifare_fuzzer_worker = malloc(sizeof(MifareFuzzerWorker)); - // Worker thread attributes - mifare_fuzzer_worker->thread = furi_thread_alloc_ex( - "MifareFuzzerWorker", 8192, mifare_fuzzer_worker_task, mifare_fuzzer_worker); - mifare_fuzzer_worker->state = MifareFuzzerWorkerStateStop; - return mifare_fuzzer_worker; -} - -/// @brief mifare_fuzzer_worker_free() -/// @param mifare_fuzzer_worker -void mifare_fuzzer_worker_free(MifareFuzzerWorker* mifare_fuzzer_worker) { - furi_assert(mifare_fuzzer_worker); - furi_thread_free(mifare_fuzzer_worker->thread); - free(mifare_fuzzer_worker); -} - -/// @brief mifare_fuzzer_worker_stop() -/// @param mifare_fuzzer_worker -void mifare_fuzzer_worker_stop(MifareFuzzerWorker* mifare_fuzzer_worker) { - furi_assert(mifare_fuzzer_worker); - if(mifare_fuzzer_worker->state != MifareFuzzerWorkerStateStop) { - mifare_fuzzer_worker->state = MifareFuzzerWorkerStateStop; - furi_thread_join(mifare_fuzzer_worker->thread); - } -} - -/// @brief mifare_fuzzer_worker_start() -/// @param mifare_fuzzer_worker -void mifare_fuzzer_worker_start(MifareFuzzerWorker* mifare_fuzzer_worker) { - furi_assert(mifare_fuzzer_worker); - mifare_fuzzer_worker->state = MifareFuzzerWorkerStateEmulate; - furi_thread_start(mifare_fuzzer_worker->thread); -} - -/// @brief mifare_fuzzer_worker_task() -/// @param context -/// @return -int32_t mifare_fuzzer_worker_task(void* context) { - MifareFuzzerWorker* mifare_fuzzer_worker = context; - - if(mifare_fuzzer_worker->state == MifareFuzzerWorkerStateEmulate) { - FuriHalNfcDevData params = mifare_fuzzer_worker->nfc_dev_data; - - furi_hal_nfc_exit_sleep(); - while(mifare_fuzzer_worker->state == MifareFuzzerWorkerStateEmulate) { - furi_hal_nfc_listen(params.uid, params.uid_len, params.atqa, params.sak, false, 500); - furi_delay_ms(50); - } - furi_hal_nfc_sleep(); - } - - mifare_fuzzer_worker->state = MifareFuzzerWorkerStateStop; - - return 0; -} - -/// @brief mifare_fuzzer_worker_is_emulating() -/// @param mifare_fuzzer_worker -/// @return -bool mifare_fuzzer_worker_is_emulating(MifareFuzzerWorker* mifare_fuzzer_worker) { - if(mifare_fuzzer_worker->state == MifareFuzzerWorkerStateEmulate) { - return true; - } - return false; -} - -/// @brief mifare_fuzzer_worker_set_nfc_dev_data() -/// @param mifare_fuzzer_worker -/// @param nfc_dev_data -void mifare_fuzzer_worker_set_nfc_dev_data( - MifareFuzzerWorker* mifare_fuzzer_worker, - FuriHalNfcDevData nfc_dev_data) { - mifare_fuzzer_worker->nfc_dev_data = nfc_dev_data; -} - -/// @brief mifare_fuzzer_worker_get_nfc_dev_data() -/// @param mifare_fuzzer_worker -/// @return -FuriHalNfcDevData mifare_fuzzer_worker_get_nfc_dev_data(MifareFuzzerWorker* mifare_fuzzer_worker) { - return mifare_fuzzer_worker->nfc_dev_data; -} diff --git a/applications/external/mifare_fuzzer/mifare_fuzzer_worker.h b/applications/external/mifare_fuzzer/mifare_fuzzer_worker.h deleted file mode 100644 index 6829f4e9e..000000000 --- a/applications/external/mifare_fuzzer/mifare_fuzzer_worker.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -#include -#include - -typedef enum MifareFuzzerWorkerState { - MifareFuzzerWorkerStateEmulate, - MifareFuzzerWorkerStateStop, -} MifareFuzzerWorkerState; - -#define UID_LEN 7 -#define ATQA_LEN 2 - -typedef struct MifareFuzzerWorker { - FuriThread* thread; - MifareFuzzerWorkerState state; - FuriHalNfcDevData nfc_dev_data; -} MifareFuzzerWorker; - -// worker -MifareFuzzerWorker* mifare_fuzzer_worker_alloc(); -void mifare_fuzzer_worker_free(MifareFuzzerWorker* mifare_fuzzer_worker); -void mifare_fuzzer_worker_stop(MifareFuzzerWorker* mifare_fuzzer_worker); -void mifare_fuzzer_worker_start(MifareFuzzerWorker* mifare_fuzzer_worker); -// task -int32_t mifare_fuzzer_worker_task(void* context); -// -bool mifare_fuzzer_worker_is_emulating(MifareFuzzerWorker* mifare_fuzzer_worker); -void mifare_fuzzer_worker_set_nfc_dev_data( - MifareFuzzerWorker* mifare_fuzzer_worker, - FuriHalNfcDevData nfc_dev_data); -FuriHalNfcDevData mifare_fuzzer_worker_get_nfc_dev_data(MifareFuzzerWorker* mifare_fuzzer_worker); diff --git a/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene.c b/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene.c deleted file mode 100644 index 1ee693eae..000000000 --- a/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "mifare_fuzzer_scene.h" - -// Generate scene on_enter handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, -void (*const mifare_fuzzer_on_enter_handlers[])(void*) = { -#include "mifare_fuzzer_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_event handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, -bool (*const mifare_fuzzer_on_event_handlers[])(void* context, SceneManagerEvent event) = { -#include "mifare_fuzzer_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_exit handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, -void (*const mifare_fuzzer_on_exit_handlers[])(void* context) = { -#include "mifare_fuzzer_scene_config.h" -}; -#undef ADD_SCENE - -// Initialize scene handlers configuration structure -const SceneManagerHandlers mifare_fuzzer_scene_handlers = { - .on_enter_handlers = mifare_fuzzer_on_enter_handlers, - .on_event_handlers = mifare_fuzzer_on_event_handlers, - .on_exit_handlers = mifare_fuzzer_on_exit_handlers, - .scene_num = MifareFuzzerSceneNum, -}; diff --git a/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene.h b/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene.h deleted file mode 100644 index e3e4cde18..000000000 --- a/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -// Generate scene id and total number -#define ADD_SCENE(prefix, name, id) MifareFuzzerScene##id, -typedef enum { -#include "mifare_fuzzer_scene_config.h" - MifareFuzzerSceneNum, -} MifareFuzzerScene; -#undef ADD_SCENE - -extern const SceneManagerHandlers mifare_fuzzer_scene_handlers; - -// Generate scene on_enter handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); -#include "mifare_fuzzer_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_event handlers declaration -#define ADD_SCENE(prefix, name, id) \ - bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); -#include "mifare_fuzzer_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_exit handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); -#include "mifare_fuzzer_scene_config.h" -#undef ADD_SCENE diff --git a/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_attack.c b/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_attack.c deleted file mode 100644 index af5be18ad..000000000 --- a/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_attack.c +++ /dev/null @@ -1,143 +0,0 @@ -#include "../mifare_fuzzer_i.h" -#include "../mifare_fuzzer_custom_events.h" - -enum SubmenuIndex { - SubmenuIndexTestValue, - SubmenuIndexRandomValuesAttack, - SubmenuIndexLoadUIDsFromFile, -}; - -/// @brief mifare_fuzzer_scene_attack_submenu_callback() -/// @param context -/// @param index -void mifare_fuzzer_scene_attack_submenu_callback(void* context, uint32_t index) { - //FURI_LOG_D(TAG, "mifare_fuzzer_scene_attack_submenu_callback() :: index = %ld", index); - MifareFuzzerApp* app = context; - uint8_t custom_event = 255; - switch(index) { - case SubmenuIndexTestValue: - custom_event = MifareFuzzerEventTestValueAttack; - break; - case SubmenuIndexRandomValuesAttack: - custom_event = MifareFuzzerEventRandomValuesAttack; - break; - case SubmenuIndexLoadUIDsFromFile: - custom_event = MifareFuzzerEventLoadUIDsFromFileAttack; - break; - default: - return; - } - //FURI_LOG_D(TAG, "mifare_fuzzer_scene_attack_submenu_callback() :: custom_event = %d", custom_event); - view_dispatcher_send_custom_event(app->view_dispatcher, custom_event); -} - -/// @brief mifare_fuzzer_scene_attack_on_enter() -/// @param context -void mifare_fuzzer_scene_attack_on_enter(void* context) { - //FURI_LOG_D(TAG, "mifare_fuzzer_scene_attack_on_enter()"); - MifareFuzzerApp* app = context; - - Submenu* submenu_attack = app->submenu_attack; - submenu_set_header(submenu_attack, "Mifare Fuzzer (attack)"); - submenu_add_item( - submenu_attack, - "Test Values", - SubmenuIndexTestValue, - mifare_fuzzer_scene_attack_submenu_callback, - app); - submenu_add_item( - submenu_attack, - "Random Values", - SubmenuIndexRandomValuesAttack, - mifare_fuzzer_scene_attack_submenu_callback, - app); - submenu_add_item( - submenu_attack, - "Load UIDs from file", - SubmenuIndexLoadUIDsFromFile, - mifare_fuzzer_scene_attack_submenu_callback, - app); - - // set selected menu - submenu_set_selected_item( - submenu_attack, - scene_manager_get_scene_state(app->scene_manager, MifareFuzzerSceneAttack)); - - view_dispatcher_switch_to_view(app->view_dispatcher, MifareFuzzerViewSelectAttack); -} - -/// @brief mifare_fuzzer_scene_attack_on_event() -/// @param context -/// @param event -/// @return -bool mifare_fuzzer_scene_attack_on_event(void* context, SceneManagerEvent event) { - //FURI_LOG_D(TAG, "mifare_fuzzer_scene_attack_on_event()"); - MifareFuzzerApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - //FURI_LOG_D(TAG, "mifare_fuzzer_scene_attack_on_event() :: event.event = %ld", event.event); - if(event.event == MifareFuzzerEventTestValueAttack) { - // save selected item - scene_manager_set_scene_state( - app->scene_manager, MifareFuzzerSceneAttack, SubmenuIndexTestValue); - // set emulator attack - app->attack = MifareFuzzerAttackTestValues; - mifare_fuzzer_emulator_set_attack(app->emulator_view, app->attack); - // open next scene - scene_manager_next_scene(app->scene_manager, MifareFuzzerSceneEmulator); - consumed = true; - } else if(event.event == MifareFuzzerEventRandomValuesAttack) { - // save selected item - scene_manager_set_scene_state( - app->scene_manager, MifareFuzzerSceneAttack, SubmenuIndexRandomValuesAttack); - // set emulator attack - app->attack = MifareFuzzerAttackRandomValues; - mifare_fuzzer_emulator_set_attack(app->emulator_view, app->attack); - // open next scene - scene_manager_next_scene(app->scene_manager, MifareFuzzerSceneEmulator); - consumed = true; - } else if(event.event == MifareFuzzerEventLoadUIDsFromFileAttack) { - // save selected item - scene_manager_set_scene_state( - app->scene_manager, MifareFuzzerSceneAttack, SubmenuIndexLoadUIDsFromFile); - // set emulator attack - app->attack = MifareFuzzerAttackLoadUidsFromFile; - mifare_fuzzer_emulator_set_attack(app->emulator_view, app->attack); - // open dialog file - DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options(&browser_options, MIFARE_FUZZER_FILE_EXT, NULL); - browser_options.hide_ext = false; - bool res = dialog_file_browser_show( - app->dialogs, app->file_path, app->app_folder, &browser_options); - if(res) { - app->uids_stream = buffered_file_stream_alloc(app->storage); - res = buffered_file_stream_open( - app->uids_stream, - furi_string_get_cstr(app->file_path), - FSAM_READ, - FSOM_OPEN_EXISTING); - if(res) { - // open next scene - scene_manager_next_scene(app->scene_manager, MifareFuzzerSceneEmulator); - } else { - buffered_file_stream_close(app->uids_stream); - } - } - consumed = true; - } - } else if(event.type == SceneManagerEventTypeTick) { - //FURI_LOG_D(TAG, "mifare_fuzzer_scene_attack_on_event() :: SceneManagerEventTypeTick"); - //consumed = true; - } - - return consumed; -} - -/// @brief mifare_fuzzer_scene_attack_on_exit() -/// @param context -void mifare_fuzzer_scene_attack_on_exit(void* context) { - //FURI_LOG_D(TAG, "mifare_fuzzer_scene_attack_on_exit()"); - MifareFuzzerApp* app = context; - submenu_reset(app->submenu_attack); -} diff --git a/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_config.h b/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_config.h deleted file mode 100644 index e93fc26e7..000000000 --- a/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_config.h +++ /dev/null @@ -1,3 +0,0 @@ -ADD_SCENE(mifare_fuzzer, start, Start) -ADD_SCENE(mifare_fuzzer, attack, Attack) -ADD_SCENE(mifare_fuzzer, emulator, Emulator) \ No newline at end of file diff --git a/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_emulator.c b/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_emulator.c deleted file mode 100644 index d2e05b7e6..000000000 --- a/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_emulator.c +++ /dev/null @@ -1,242 +0,0 @@ -#include "../mifare_fuzzer_i.h" - -uint8_t tick_counter = 0; -uint8_t attack_step = 0; - -uint8_t id_uid_test[9][7] = { - {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17}, - {0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28}, - {0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39}, - {0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a}, - {0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b}, - {0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c}, - {0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d}, - {0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e}, - {0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f}, -}; - -/// @brief mifare_fuzzer_scene_emulator_callback() -/// @param event -/// @param context -static void mifare_fuzzer_scene_emulator_callback(MifareFuzzerEvent event, void* context) { - //FURI_LOG_D(TAG, "mifare_fuzzer_scene_emulator_callback()"); - furi_assert(context); - MifareFuzzerApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, event); -} - -/// @brief mifare_fuzzer_scene_emulator_on_enter() -/// @param context -void mifare_fuzzer_scene_emulator_on_enter(void* context) { - //FURI_LOG_D(TAG, "mifare_fuzzer_scene_emulator_on_enter()"); - MifareFuzzerApp* app = context; - MifareFuzzerEmulator* emulator = app->emulator_view; - - // init callback - mifare_fuzzer_emulator_set_callback(emulator, mifare_fuzzer_scene_emulator_callback, app); - // init ticks - tick_counter = 0; - mifare_fuzzer_emulator_set_tick_num(app->emulator_view, tick_counter); - emulator->ticks_between_cards = MIFARE_FUZZER_DEFAULT_TICKS_BETWEEN_CARDS; - mifare_fuzzer_emulator_set_ticks_between_cards( - app->emulator_view, emulator->ticks_between_cards); - // init default card data - FuriHalNfcDevData nfc_dev_data; - nfc_dev_data.atqa[0] = 0x00; - nfc_dev_data.atqa[1] = 0x00; - nfc_dev_data.sak = 0x00; - if(app->card == MifareCardUltralight) { - nfc_dev_data.uid_len = 0x07; - } else { - nfc_dev_data.uid_len = 0x04; - } - for(uint32_t i = 0; i < nfc_dev_data.uid_len; i++) { - nfc_dev_data.uid[i] = 0x00; - } - mifare_fuzzer_emulator_set_nfc_dev_data(app->emulator_view, nfc_dev_data); - // init other vars - attack_step = 0; - - // switch to view - view_dispatcher_switch_to_view(app->view_dispatcher, MifareFuzzerViewEmulator); -} - -/// @brief mifare_fuzzer_scene_emulator_on_event() -/// @param context -/// @param event -/// @return -bool mifare_fuzzer_scene_emulator_on_event(void* context, SceneManagerEvent event) { - //FURI_LOG_D(TAG, "mifare_fuzzer_scene_emulator_on_event()"); - FuriHalNfcDevData nfc_dev_data; - - MifareFuzzerApp* app = context; - MifareFuzzerEmulator* emulator = app->emulator_view; - - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == MifareFuzzerEventStartAttack) { - //FURI_LOG_D(TAG, "mifare_fuzzer_scene_emulator_on_event() :: MifareFuzzerEventStartAttack"); - - // Stop worker - mifare_fuzzer_worker_stop(app->worker); - - // Set card type - // TODO: Move somewhere else, I do not like this to be there - if(app->card == MifareCardClassic1k) { - nfc_dev_data.atqa[0] = 0x04; - nfc_dev_data.atqa[1] = 0x00; - nfc_dev_data.sak = 0x08; - nfc_dev_data.uid_len = 0x04; - } else if(app->card == MifareCardClassic4k) { - nfc_dev_data.atqa[0] = 0x02; - nfc_dev_data.atqa[1] = 0x00; - nfc_dev_data.sak = 0x18; - nfc_dev_data.uid_len = 0x04; - } else if(app->card == MifareCardUltralight) { - nfc_dev_data.atqa[0] = 0x44; - nfc_dev_data.atqa[1] = 0x00; - nfc_dev_data.sak = 0x00; - nfc_dev_data.uid_len = 0x07; - } - - // Set UIDs - if(app->attack == MifareFuzzerAttackTestValues) { - // Load test UIDs - for(uint8_t i = 0; i < nfc_dev_data.uid_len; i++) { - nfc_dev_data.uid[i] = id_uid_test[attack_step][i]; - } - // Next UIDs on next loop - if(attack_step >= 8) { - attack_step = 0; - } else { - attack_step++; - } - } else if(app->attack == MifareFuzzerAttackRandomValues) { - if(app->card == MifareCardUltralight) { - // First byte of a 7 byte UID is the manufacturer-code - // https://github.com/Proxmark/proxmark3/blob/master/client/taginfo.c - // https://stackoverflow.com/questions/37837730/mifare-cards-distinguish-between-4-byte-and-7-byte-uids - // https://stackoverflow.com/questions/31233652/how-to-detect-manufacturer-from-nfc-tag-using-android - - // TODO: Manufacture-code must be selectable from a list - // use a fixed manufacture-code for now: 0x04 = NXP Semiconductors Germany - nfc_dev_data.uid[0] = 0x04; - for(uint8_t i = 1; i < nfc_dev_data.uid_len; i++) { - nfc_dev_data.uid[i] = (furi_hal_random_get() & 0xFF); - } - } else { - for(uint8_t i = 0; i < nfc_dev_data.uid_len; i++) { - nfc_dev_data.uid[i] = (furi_hal_random_get() & 0xFF); - } - } - } else if(app->attack == MifareFuzzerAttackLoadUidsFromFile) { - //bool end_of_list = false; - // read stream - while(true) { - furi_string_reset(app->uid_str); - if(!stream_read_line(app->uids_stream, app->uid_str)) { - // restart from beginning on empty line - stream_rewind(app->uids_stream); - continue; - //end_of_list = true; - } - // Skip comments - if(furi_string_get_char(app->uid_str, 0) == '#') continue; - // Skip lines with invalid length - if((furi_string_size(app->uid_str) != 9) && - (furi_string_size(app->uid_str) != 15)) - continue; - break; - } - - // TODO: stop on end of list? - //if(end_of_list) break; - - // parse string to UID - // TODO: a better validation on input? - for(uint8_t i = 0; i < nfc_dev_data.uid_len; i++) { - if(i <= ((furi_string_size(app->uid_str) - 1) / 2)) { - char temp_str[3]; - temp_str[0] = furi_string_get_cstr(app->uid_str)[i * 2]; - temp_str[1] = furi_string_get_cstr(app->uid_str)[i * 2 + 1]; - temp_str[2] = '\0'; - nfc_dev_data.uid[i] = (uint8_t)strtol(temp_str, NULL, 16); - } else { - nfc_dev_data.uid[i] = 0x00; - } - } - } - - mifare_fuzzer_worker_set_nfc_dev_data(app->worker, nfc_dev_data); - mifare_fuzzer_emulator_set_nfc_dev_data(app->emulator_view, nfc_dev_data); - - // Reset tick_counter - tick_counter = 0; - mifare_fuzzer_emulator_set_tick_num(app->emulator_view, tick_counter); - - // Start worker - mifare_fuzzer_worker_start(app->worker); - - } else if(event.event == MifareFuzzerEventStopAttack) { - //FURI_LOG_D(TAG, "mifare_fuzzer_scene_emulator_on_event() :: MifareFuzzerEventStopAttack"); - // Stop worker - mifare_fuzzer_worker_stop(app->worker); - } else if(event.event == MifareFuzzerEventIncrementTicks) { - if(!emulator->is_attacking) { - if(emulator->ticks_between_cards < MIFARE_FUZZER_MAX_TICKS_BETWEEN_CARDS) { - emulator->ticks_between_cards++; - mifare_fuzzer_emulator_set_ticks_between_cards( - app->emulator_view, emulator->ticks_between_cards); - }; - }; - } else if(event.event == MifareFuzzerEventDecrementTicks) { - if(!emulator->is_attacking) { - if(emulator->ticks_between_cards > MIFARE_FUZZER_MIN_TICKS_BETWEEN_CARDS) { - emulator->ticks_between_cards--; - mifare_fuzzer_emulator_set_ticks_between_cards( - app->emulator_view, emulator->ticks_between_cards); - }; - }; - } - consumed = true; - } else if(event.type == SceneManagerEventTypeTick) { - //FURI_LOG_D(TAG, "mifare_fuzzer_scene_emulator_on_event() :: SceneManagerEventTypeTick"); - - // Used to check tick length (not perfect but enough) - //FuriHalRtcDateTime curr_dt; - //furi_hal_rtc_get_datetime(&curr_dt); - //FURI_LOG_D(TAG, "Time is: %.2d:%.2d:%.2d", curr_dt.hour, curr_dt.minute, curr_dt.second); - - // If emulator is attacking - if(emulator->is_attacking) { - // increment tick_counter - tick_counter++; - mifare_fuzzer_emulator_set_tick_num(app->emulator_view, tick_counter); - //FURI_LOG_D(TAG, "tick_counter is: %.2d", tick_counter); - if(tick_counter >= emulator->ticks_between_cards) { - // Queue event for changing UID - view_dispatcher_send_custom_event( - app->view_dispatcher, MifareFuzzerEventStartAttack); - } - } - - consumed = true; - } - - return consumed; -} - -/// @brief mifare_fuzzer_scene_emulator_on_exit() -/// @param context -void mifare_fuzzer_scene_emulator_on_exit(void* context) { - //FURI_LOG_D(TAG, "mifare_fuzzer_scene_emulator_on_exit()"); - MifareFuzzerApp* app = context; - mifare_fuzzer_worker_stop(app->worker); - - if(app->attack == MifareFuzzerAttackLoadUidsFromFile) { - furi_string_reset(app->uid_str); - stream_rewind(app->uids_stream); - buffered_file_stream_close(app->uids_stream); - } -} diff --git a/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_start.c b/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_start.c deleted file mode 100644 index 443f117f4..000000000 --- a/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_start.c +++ /dev/null @@ -1,124 +0,0 @@ -#include "../mifare_fuzzer_i.h" -#include "../mifare_fuzzer_custom_events.h" - -enum SubmenuIndex { - SubmenuIndexClassic1k, - SubmenuIndexClassic4k, - SubmenuIndexUltralight, -}; - -/// @brief mifare_fuzzer_scene_start_submenu_callback() -/// @param context -/// @param index -void mifare_fuzzer_scene_start_submenu_callback(void* context, uint32_t index) { - //FURI_LOG_D(TAG, "mifare_fuzzer_scene_start_submenu_callback() :: index = %ld", index); - MifareFuzzerApp* app = context; - uint8_t custom_event = 255; - switch(index) { - case SubmenuIndexClassic1k: - custom_event = MifareFuzzerEventClassic1k; - break; - case SubmenuIndexClassic4k: - custom_event = MifareFuzzerEventClassic4k; - break; - case SubmenuIndexUltralight: - custom_event = MifareFuzzerEventUltralight; - break; - default: - return; - } - //FURI_LOG_D(TAG, "mifare_fuzzer_scene_start_submenu_callback() :: custom_event = %d", custom_event); - view_dispatcher_send_custom_event(app->view_dispatcher, custom_event); -} - -/// @brief mifare_fuzzer_scene_start_on_enter() -/// @param context -void mifare_fuzzer_scene_start_on_enter(void* context) { - //FURI_LOG_D(TAG, "mifare_fuzzer_scene_start_on_enter()"); - MifareFuzzerApp* app = context; - - Submenu* submenu_card = app->submenu_card; - submenu_set_header(submenu_card, "Mifare Fuzzer (card)"); - submenu_add_item( - submenu_card, - "Classic 1k", - SubmenuIndexClassic1k, - mifare_fuzzer_scene_start_submenu_callback, - app); - submenu_add_item( - submenu_card, - "Classic 4k", - SubmenuIndexClassic4k, - mifare_fuzzer_scene_start_submenu_callback, - app); - submenu_add_item( - submenu_card, - "Ultralight", - SubmenuIndexUltralight, - mifare_fuzzer_scene_start_submenu_callback, - app); - - // set selected menu - submenu_set_selected_item( - submenu_card, scene_manager_get_scene_state(app->scene_manager, MifareFuzzerSceneStart)); - - view_dispatcher_switch_to_view(app->view_dispatcher, MifareFuzzerViewSelectCard); -} - -/// @brief mifare_fuzzer_scene_start_on_event() -/// @param context -/// @param event -/// @return -bool mifare_fuzzer_scene_start_on_event(void* context, SceneManagerEvent event) { - //FURI_LOG_D(TAG, "mifare_fuzzer_scene_start_on_event()"); - MifareFuzzerApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - //FURI_LOG_D(TAG, "mifare_fuzzer_scene_start_on_event() :: event.event = %ld", event.event); - if(event.event == MifareFuzzerEventClassic1k) { - // save selected item - scene_manager_set_scene_state( - app->scene_manager, MifareFuzzerSceneStart, SubmenuIndexClassic1k); - // set emulator card - app->card = MifareCardClassic1k; - mifare_fuzzer_emulator_set_card(app->emulator_view, app->card); - // open next scene - scene_manager_next_scene(app->scene_manager, MifareFuzzerSceneAttack); - consumed = true; - } else if(event.event == MifareFuzzerEventClassic4k) { - // save selected item - scene_manager_set_scene_state( - app->scene_manager, MifareFuzzerSceneStart, SubmenuIndexClassic4k); - // set emulator card - app->card = MifareCardClassic4k; - mifare_fuzzer_emulator_set_card(app->emulator_view, app->card); - // open next scene - scene_manager_next_scene(app->scene_manager, MifareFuzzerSceneAttack); - consumed = true; - } else if(event.event == MifareFuzzerEventUltralight) { - // save selected item - scene_manager_set_scene_state( - app->scene_manager, MifareFuzzerSceneStart, SubmenuIndexUltralight); - // set emulator card - app->card = MifareCardUltralight; - mifare_fuzzer_emulator_set_card(app->emulator_view, app->card); - // open next scene - scene_manager_next_scene(app->scene_manager, MifareFuzzerSceneAttack); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeTick) { - //FURI_LOG_D(TAG, "mifare_fuzzer_scene_start_on_event() :: SceneManagerEventTypeTick"); - //consumed = true; - } - - return consumed; -} - -/// @brief mifare_fuzzer_scene_start_on_exit() -/// @param context -void mifare_fuzzer_scene_start_on_exit(void* context) { - //FURI_LOG_D(TAG, "mifare_fuzzer_scene_start_on_exit()"); - MifareFuzzerApp* app = context; - submenu_reset(app->submenu_card); -} diff --git a/applications/external/mifare_fuzzer/views/mifare_fuzzer_emulator.c b/applications/external/mifare_fuzzer/views/mifare_fuzzer_emulator.c deleted file mode 100644 index d4925e02b..000000000 --- a/applications/external/mifare_fuzzer/views/mifare_fuzzer_emulator.c +++ /dev/null @@ -1,301 +0,0 @@ -#include "mifare_fuzzer_emulator.h" - -#define TAG "MifareFuzzerApp_emulator_view" - -// Screen is 128 × 64 pixels - -/// @brief mifare_fuzzer_emulator_set_callback -/// @param mifare_fuzzer_emulator -/// @param callback -/// @param context -void mifare_fuzzer_emulator_set_callback( - MifareFuzzerEmulator* mifare_fuzzer_emulator, - MifareFuzzerEmulatorCallback callback, - void* context) { - furi_assert(mifare_fuzzer_emulator); - furi_assert(callback); - - mifare_fuzzer_emulator->callback = callback; - mifare_fuzzer_emulator->context = context; -} - -/// @brief mifare_fuzzer_emulator_draw_callback -/// @param canvas -/// @param _model -static void mifare_fuzzer_emulator_draw_callback(Canvas* canvas, void* _model) { - MifareFuzzerEmulatorModel* model = _model; - FuriString* furi_string = furi_string_alloc(); - - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - - // Primary font - canvas_set_font(canvas, FontPrimary); - // Title - canvas_draw_str(canvas, 4, 11, model->title); - - // Emulated UID - uint8_t cpos; - char uid[25]; - char uid_char[3]; - cpos = 0; - for(uint8_t i = 0; i < model->nfc_dev_data.uid_len; i++) { - if(i > 0) { - uid[cpos] = ':'; - cpos++; - } - snprintf(uid_char, sizeof(uid_char), "%02X", model->nfc_dev_data.uid[i]); - uid[cpos] = uid_char[0]; - cpos++; - uid[cpos] = uid_char[1]; - cpos++; - } - uid[cpos] = 0x00; - canvas_draw_str_aligned(canvas, 128 / 2, 43, AlignCenter, AlignCenter, uid); - - // Secondary font - canvas_set_font(canvas, FontSecondary); - // Card - canvas_draw_str(canvas, 4, 22, "c:"); - canvas_draw_str(canvas, 15, 22, model->mifare_card_dsc); - // Timing - furi_string_printf(furi_string, "%d", model->ticks_between_cards); - canvas_draw_str(canvas, 90, 22, "t:"); - canvas_draw_str(canvas, 100, 22, furi_string_get_cstr(furi_string)); - // Attack - canvas_draw_str(canvas, 4, 33, "a:"); - canvas_draw_str(canvas, 15, 33, model->attack_dsc); - - if(!model->is_attacking) { - elements_button_left(canvas, "t-1"); - elements_button_center(canvas, "Start"); - elements_button_right(canvas, "t+1"); - } else { - canvas_draw_line(canvas, 1, 49, (128 * model->tick_num / model->ticks_between_cards), 49); - elements_button_center(canvas, "Stop"); - } - - // Free temp string - furi_string_free(furi_string); -} - -/// @brief mifare_fuzzer_emulator_input_callback -/// @param event -/// @param context -/// @return -static bool mifare_fuzzer_emulator_input_callback(InputEvent* event, void* context) { - //FURI_LOG_D(TAG, "mifare_fuzzer_emulator_input_callback()"); - furi_assert(context); - MifareFuzzerEmulator* mifare_fuzzer_emulator = context; - bool consumed = false; - - if(event->type == InputTypeShort) { - if(event->key == InputKeyRight) { - if(!mifare_fuzzer_emulator->is_attacking) { - mifare_fuzzer_emulator->callback( - MifareFuzzerEventIncrementTicks, mifare_fuzzer_emulator->context); - }; - consumed = true; - } else if(event->key == InputKeyLeft) { - if(!mifare_fuzzer_emulator->is_attacking) { - mifare_fuzzer_emulator->callback( - MifareFuzzerEventDecrementTicks, mifare_fuzzer_emulator->context); - }; - consumed = true; - } else if(event->key == InputKeyUp) { - consumed = true; - } else if(event->key == InputKeyDown) { - consumed = true; - } else if(event->key == InputKeyOk) { - // Toggle attack - if(mifare_fuzzer_emulator->is_attacking) { - mifare_fuzzer_emulator->is_attacking = false; - mifare_fuzzer_emulator->callback( - MifareFuzzerEventStopAttack, mifare_fuzzer_emulator->context); - } else { - mifare_fuzzer_emulator->is_attacking = true; - mifare_fuzzer_emulator->callback( - MifareFuzzerEventStartAttack, mifare_fuzzer_emulator->context); - } - - with_view_model( - mifare_fuzzer_emulator->view, - MifareFuzzerEmulatorModel * model, - { model->is_attacking = mifare_fuzzer_emulator->is_attacking; }, - true); - - consumed = true; - } - } - - return consumed; -} - -/// @brief mifare_fuzzer_emulator_enter_callback -/// @param context -static void mifare_fuzzer_emulator_enter_callback(void* context) { - //FURI_LOG_D(TAG, "mifare_fuzzer_emulator_enter_callback()"); - furi_assert(context); - MifareFuzzerEmulator* mifare_fuzzer_emulator = context; - - //UNUSED(mifare_fuzzer_emulator); - mifare_fuzzer_emulator->is_attacking = false; - with_view_model( - mifare_fuzzer_emulator->view, - MifareFuzzerEmulatorModel * model, - { model->is_attacking = false; }, - true); -} - -/// @brief mifare_fuzzer_emulator_alloc -/// @return -MifareFuzzerEmulator* mifare_fuzzer_emulator_alloc() { - MifareFuzzerEmulator* mifare_fuzzer_emulator = malloc(sizeof(MifareFuzzerEmulator)); - mifare_fuzzer_emulator->view = view_alloc(); - view_set_context(mifare_fuzzer_emulator->view, mifare_fuzzer_emulator); - view_allocate_model( - mifare_fuzzer_emulator->view, ViewModelTypeLocking, sizeof(MifareFuzzerEmulatorModel)); - view_set_draw_callback(mifare_fuzzer_emulator->view, mifare_fuzzer_emulator_draw_callback); - view_set_input_callback(mifare_fuzzer_emulator->view, mifare_fuzzer_emulator_input_callback); - view_set_enter_callback(mifare_fuzzer_emulator->view, mifare_fuzzer_emulator_enter_callback); - - with_view_model( - mifare_fuzzer_emulator->view, - MifareFuzzerEmulatorModel * model, - { model->title = "Mifare Fuzzer (emulator)"; }, - true); - - return mifare_fuzzer_emulator; -} - -/// @brief mifare_fuzzer_emulator_free -/// @param context -void mifare_fuzzer_emulator_free(MifareFuzzerEmulator* context) { - //FURI_LOG_D(TAG, "mifare_fuzzer_emulator_free()"); - furi_assert(context); - MifareFuzzerEmulator* mifare_fuzzer_emulator = context; - /* - with_view_model( - mifare_fuzzer_emulator->view, - MifareFuzzerEmulatorModel* model, - { - UNUSED(model); - }, - true - ); - */ - - view_free(mifare_fuzzer_emulator->view); - free(mifare_fuzzer_emulator); -} - -/// @brief mifare_fuzzer_emulator_get_view -/// @param mifare_fuzzer_emulator -/// @return -View* mifare_fuzzer_emulator_get_view(MifareFuzzerEmulator* mifare_fuzzer_emulator) { - furi_assert(mifare_fuzzer_emulator); - return mifare_fuzzer_emulator->view; -} - -/// @brief Set card type -/// @param mifare_fuzzer_emulator -/// @param mifare_card -void mifare_fuzzer_emulator_set_card( - MifareFuzzerEmulator* mifare_fuzzer_emulator, - MifareCard mifare_card) { - furi_assert(mifare_fuzzer_emulator); - furi_assert(mifare_card); - - with_view_model( - mifare_fuzzer_emulator->view, - MifareFuzzerEmulatorModel * model, - { - model->mifare_card = mifare_card; - switch(mifare_card) { - case MifareCardClassic1k: - model->mifare_card_dsc = "Classic 1k"; - break; - case MifareCardClassic4k: - model->mifare_card_dsc = "Classic 4k"; - break; - case MifareCardUltralight: - model->mifare_card_dsc = "Ultralight"; - break; - } - }, - true); -} - -/// @brief Set attack type -/// @param mifare_fuzzer_emulator -/// @param mifare_attack -void mifare_fuzzer_emulator_set_attack( - MifareFuzzerEmulator* mifare_fuzzer_emulator, - MifareFuzzerAttack mifare_attack) { - furi_assert(mifare_fuzzer_emulator); - furi_assert(mifare_attack); - - with_view_model( - mifare_fuzzer_emulator->view, - MifareFuzzerEmulatorModel * model, - { - model->attack = mifare_attack; - switch(mifare_attack) { - case MifareFuzzerAttackTestValues: - model->attack_dsc = "Test values"; - break; - case MifareFuzzerAttackRandomValues: - model->attack_dsc = "Random values"; - break; - case MifareFuzzerAttackLoadUidsFromFile: - model->attack_dsc = "Load Uids From File"; - break; - } - }, - true); -} - -/// @brief mifare_fuzzer_emulator_set_nfc_dev_data -/// @param mifare_fuzzer_emulator -/// @param nfc_dev_data -void mifare_fuzzer_emulator_set_nfc_dev_data( - MifareFuzzerEmulator* mifare_fuzzer_emulator, - FuriHalNfcDevData nfc_dev_data) { - furi_assert(mifare_fuzzer_emulator); - - with_view_model( - mifare_fuzzer_emulator->view, - MifareFuzzerEmulatorModel * model, - { model->nfc_dev_data = nfc_dev_data; }, - true); -} - -/// @brief mifare_fuzzer_emulator_set_ticks_between_cards -/// @param mifare_fuzzer_emulator -/// @param ticks -void mifare_fuzzer_emulator_set_ticks_between_cards( - MifareFuzzerEmulator* mifare_fuzzer_emulator, - uint8_t ticks) { - furi_assert(mifare_fuzzer_emulator); - - with_view_model( - mifare_fuzzer_emulator->view, - MifareFuzzerEmulatorModel * model, - { model->ticks_between_cards = ticks; }, - true); -} - -/// @brief mifare_fuzzer_emulator_set_tick_num -/// @param mifare_fuzzer_emulator -/// @param tick_num -void mifare_fuzzer_emulator_set_tick_num( - MifareFuzzerEmulator* mifare_fuzzer_emulator, - uint8_t tick_num) { - furi_assert(mifare_fuzzer_emulator); - - with_view_model( - mifare_fuzzer_emulator->view, - MifareFuzzerEmulatorModel * model, - { model->tick_num = tick_num; }, - true); -} diff --git a/applications/external/mifare_fuzzer/views/mifare_fuzzer_emulator.h b/applications/external/mifare_fuzzer/views/mifare_fuzzer_emulator.h deleted file mode 100644 index 30e56f4dd..000000000 --- a/applications/external/mifare_fuzzer/views/mifare_fuzzer_emulator.h +++ /dev/null @@ -1,70 +0,0 @@ -#pragma once -#include "../mifare_fuzzer_custom_events.h" -#include -#include -#include -#include - -typedef void (*MifareFuzzerEmulatorCallback)(MifareFuzzerEvent event, void* context); - -typedef enum MifareCard { - MifareCardClassic1k = 1, - MifareCardClassic4k, - MifareCardUltralight, -} MifareCard; - -typedef enum MifareFuzzerAttack { - MifareFuzzerAttackTestValues = 1, - MifareFuzzerAttackRandomValues, - MifareFuzzerAttackLoadUidsFromFile, -} MifareFuzzerAttack; - -typedef struct MifareFuzzerEmulator { - View* view; - MifareFuzzerEmulatorCallback callback; - void* context; - bool is_attacking; - uint8_t ticks_between_cards; -} MifareFuzzerEmulator; - -typedef struct MifareFuzzerEmulatorModel { - const char* title; - MifareCard mifare_card; - const char* mifare_card_dsc; - MifareFuzzerAttack attack; - const char* attack_dsc; - FuriHalNfcDevData nfc_dev_data; - bool is_attacking; - uint8_t tick_num; - uint8_t ticks_between_cards; -} MifareFuzzerEmulatorModel; - -MifareFuzzerEmulator* mifare_fuzzer_emulator_alloc(); - -void mifare_fuzzer_emulator_free(MifareFuzzerEmulator* context); - -View* mifare_fuzzer_emulator_get_view(MifareFuzzerEmulator* context); - -void mifare_fuzzer_emulator_set_card( - MifareFuzzerEmulator* mifare_fuzzer_emulator, - MifareCard mifare_card); -void mifare_fuzzer_emulator_set_attack( - MifareFuzzerEmulator* mifare_fuzzer_emulator, - MifareFuzzerAttack mifare_attack); - -void mifare_fuzzer_emulator_set_callback( - MifareFuzzerEmulator* mifare_fuzzer_emulator, - MifareFuzzerEmulatorCallback callback, - void* context); - -void mifare_fuzzer_emulator_set_nfc_dev_data( - MifareFuzzerEmulator* mifare_fuzzer_emulator, - FuriHalNfcDevData nfc_dev_data); - -void mifare_fuzzer_emulator_set_ticks_between_cards( - MifareFuzzerEmulator* mifare_fuzzer_emulator, - uint8_t ticks); - -void mifare_fuzzer_emulator_set_tick_num( - MifareFuzzerEmulator* mifare_fuzzer_emulator, - uint8_t tick_num); diff --git a/applications/external/mifare_nested/LICENSE.md b/applications/external/mifare_nested/LICENSE.md deleted file mode 100644 index f288702d2..000000000 --- a/applications/external/mifare_nested/LICENSE.md +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/applications/external/mifare_nested/application.fam b/applications/external/mifare_nested/application.fam deleted file mode 100644 index a06f7d7ec..000000000 --- a/applications/external/mifare_nested/application.fam +++ /dev/null @@ -1,16 +0,0 @@ -App( - appid="mifare_nested", - name="Mifare Nested", - apptype=FlipperAppType.EXTERNAL, - entry_point="mifare_nested_app", - requires=["storage", "gui", "nfc"], - stack_size=4 * 1024, - fap_icon="assets/icon.png", - fap_category="NFC", - fap_private_libs=[Lib(name="nested"), Lib(name="parity"), Lib(name="crypto1")], - fap_icon_assets="assets", - fap_author="AloneLiberty", - fap_description="Recover Mifare Classic keys", - fap_weburl="https://github.com/AloneLiberty/FlipperNested", - fap_version="1.5.2", -) diff --git a/applications/external/mifare_nested/assets/ApplyTag.png b/applications/external/mifare_nested/assets/ApplyTag.png deleted file mode 100644 index 787c0bcfe..000000000 Binary files a/applications/external/mifare_nested/assets/ApplyTag.png and /dev/null differ diff --git a/applications/external/mifare_nested/assets/DolphinCry.png b/applications/external/mifare_nested/assets/DolphinCry.png deleted file mode 100644 index 86d9db1b4..000000000 Binary files a/applications/external/mifare_nested/assets/DolphinCry.png and /dev/null differ diff --git a/applications/external/mifare_nested/assets/DolphinSuccess.png b/applications/external/mifare_nested/assets/DolphinSuccess.png deleted file mode 100644 index 341999109..000000000 Binary files a/applications/external/mifare_nested/assets/DolphinSuccess.png and /dev/null differ diff --git a/applications/external/mifare_nested/assets/Loading.png b/applications/external/mifare_nested/assets/Loading.png deleted file mode 100644 index 93a59fe68..000000000 Binary files a/applications/external/mifare_nested/assets/Loading.png and /dev/null differ diff --git a/applications/external/mifare_nested/assets/icon.png b/applications/external/mifare_nested/assets/icon.png deleted file mode 100644 index ae72f2ff9..000000000 Binary files a/applications/external/mifare_nested/assets/icon.png and /dev/null differ diff --git a/applications/external/mifare_nested/lib/crypto1/crypto1.c b/applications/external/mifare_nested/lib/crypto1/crypto1.c deleted file mode 100644 index 0483f45e8..000000000 --- a/applications/external/mifare_nested/lib/crypto1/crypto1.c +++ /dev/null @@ -1,118 +0,0 @@ -#include "crypto1.h" -#include - -void crypto1_reset(Crypto1* crypto1) { - furi_assert(crypto1); - crypto1->even = 0; - crypto1->odd = 0; -} - -void crypto1_init(Crypto1* crypto1, uint64_t key) { - furi_assert(crypto1); - crypto1->even = 0; - crypto1->odd = 0; - for(int8_t i = 47; i > 0; i -= 2) { - crypto1->odd = crypto1->odd << 1 | FURI_BIT(key, (i - 1) ^ 7); - crypto1->even = crypto1->even << 1 | FURI_BIT(key, i ^ 7); - } -} - -uint32_t crypto1_filter(uint32_t in) { - uint32_t out = 0; - out = 0xf22c0 >> (in & 0xf) & 16; - out |= 0x6c9c0 >> (in >> 4 & 0xf) & 8; - out |= 0x3c8b0 >> (in >> 8 & 0xf) & 4; - out |= 0x1e458 >> (in >> 12 & 0xf) & 2; - out |= 0x0d938 >> (in >> 16 & 0xf) & 1; - return FURI_BIT(0xEC57E80A, out); -} - -uint8_t crypto1_bit(Crypto1* crypto1, uint8_t in, int is_encrypted) { - furi_assert(crypto1); - uint8_t out = crypto1_filter(crypto1->odd); - uint32_t feed = out & (!!is_encrypted); - feed ^= !!in; - feed ^= LF_POLY_ODD & crypto1->odd; - feed ^= LF_POLY_EVEN & crypto1->even; - crypto1->even = crypto1->even << 1 | (evenparity32(feed)); - - FURI_SWAP(crypto1->odd, crypto1->even); - return out; -} - -uint8_t crypto1_byte(Crypto1* crypto1, uint8_t in, int is_encrypted) { - furi_assert(crypto1); - uint8_t out = 0; - for(uint8_t i = 0; i < 8; i++) { - out |= crypto1_bit(crypto1, FURI_BIT(in, i), is_encrypted) << i; - } - return out; -} - -uint32_t crypto1_word(Crypto1* crypto1, uint32_t in, int is_encrypted) { - furi_assert(crypto1); - uint32_t out = 0; - for(uint8_t i = 0; i < 32; i++) { - out |= (uint32_t)crypto1_bit(crypto1, BEBIT(in, i), is_encrypted) << (24 ^ i); - } - return out; -} - -uint32_t prng_successor(uint32_t x, uint32_t n) { - SWAPENDIAN(x); - while(n--) x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31; - - return SWAPENDIAN(x); -} - -void crypto1_decrypt( - Crypto1* crypto, - uint8_t* encrypted_data, - uint16_t encrypted_data_bits, - uint8_t* decrypted_data) { - furi_assert(crypto); - furi_assert(encrypted_data); - furi_assert(decrypted_data); - - if(encrypted_data_bits < 8) { - uint8_t decrypted_byte = 0; - decrypted_byte |= (crypto1_bit(crypto, 0, 0) ^ FURI_BIT(encrypted_data[0], 0)) << 0; - decrypted_byte |= (crypto1_bit(crypto, 0, 0) ^ FURI_BIT(encrypted_data[0], 1)) << 1; - decrypted_byte |= (crypto1_bit(crypto, 0, 0) ^ FURI_BIT(encrypted_data[0], 2)) << 2; - decrypted_byte |= (crypto1_bit(crypto, 0, 0) ^ FURI_BIT(encrypted_data[0], 3)) << 3; - decrypted_data[0] = decrypted_byte; - } else { - for(size_t i = 0; i < encrypted_data_bits / 8; i++) { - decrypted_data[i] = crypto1_byte(crypto, 0, 0) ^ encrypted_data[i]; - } - } -} - -void crypto1_encrypt( - Crypto1* crypto, - uint8_t* keystream, - uint8_t* plain_data, - uint16_t plain_data_bits, - uint8_t* encrypted_data, - uint8_t* encrypted_parity) { - furi_assert(crypto); - furi_assert(plain_data); - furi_assert(encrypted_data); - furi_assert(encrypted_parity); - - if(plain_data_bits < 8) { - encrypted_data[0] = 0; - for(size_t i = 0; i < plain_data_bits; i++) { - encrypted_data[0] |= (crypto1_bit(crypto, 0, 0) ^ FURI_BIT(plain_data[0], i)) << i; - } - } else { - memset(encrypted_parity, 0, plain_data_bits / 8 + 1); - for(uint8_t i = 0; i < plain_data_bits / 8; i++) { - encrypted_data[i] = crypto1_byte(crypto, keystream ? keystream[i] : 0, 0) ^ - plain_data[i]; - encrypted_parity[i / 8] |= - (((crypto1_filter(crypto->odd) ^ oddparity8(plain_data[i])) & 0x01) - << (7 - (i & 0x0007))); - } - } -} \ No newline at end of file diff --git a/applications/external/mifare_nested/lib/crypto1/crypto1.h b/applications/external/mifare_nested/lib/crypto1/crypto1.h deleted file mode 100644 index bad6e631b..000000000 --- a/applications/external/mifare_nested/lib/crypto1/crypto1.h +++ /dev/null @@ -1,39 +0,0 @@ -#include "../../lib/parity/parity.h" -#include -#include -#include "stddef.h" - -#define LF_POLY_ODD (0x29CE5C) -#define LF_POLY_EVEN (0x870804) - -#define SWAPENDIAN(x) \ - ((x) = ((x) >> 8 & 0xff00ff) | ((x)&0xff00ff) << 8, (x) = (x) >> 16 | (x) << 16) -#define BEBIT(x, n) FURI_BIT(x, (n) ^ 24) - -void crypto1_reset(Crypto1* crypto1); - -void crypto1_init(Crypto1* crypto1, uint64_t key); - -uint32_t crypto1_filter(uint32_t in); - -uint8_t crypto1_bit(Crypto1* crypto1, uint8_t in, int is_encrypted); - -uint8_t crypto1_byte(Crypto1* crypto1, uint8_t in, int is_encrypted); - -uint32_t crypto1_word(Crypto1* crypto1, uint32_t in, int is_encrypted); - -uint32_t prng_successor(uint32_t x, uint32_t n); - -void crypto1_decrypt( - Crypto1* crypto, - uint8_t* encrypted_data, - uint16_t encrypted_data_bits, - uint8_t* decrypted_data); - -void crypto1_encrypt( - Crypto1* crypto, - uint8_t* keystream, - uint8_t* plain_data, - uint16_t plain_data_bits, - uint8_t* encrypted_data, - uint8_t* encrypted_parity); \ No newline at end of file diff --git a/applications/external/mifare_nested/lib/nested/nested.c b/applications/external/mifare_nested/lib/nested/nested.c deleted file mode 100644 index b289b74fb..000000000 --- a/applications/external/mifare_nested/lib/nested/nested.c +++ /dev/null @@ -1,718 +0,0 @@ -#include "nested.h" - -#include -#include "../../lib/parity/parity.h" -#include "../../lib/crypto1/crypto1.h" -#define TAG "Nested" - -uint16_t nfca_get_crc16(uint8_t* buff, uint16_t len) { - uint16_t crc = 0x6363; // NFCA_CRC_INIT - uint8_t byte = 0; - - for(uint8_t i = 0; i < len; i++) { - byte = buff[i]; - byte ^= (uint8_t)(crc & 0xff); - byte ^= byte << 4; - crc = (crc >> 8) ^ (((uint16_t)byte) << 8) ^ (((uint16_t)byte) << 3) ^ - (((uint16_t)byte) >> 4); - } - - return crc; -} - -void nfca_append_crc16(uint8_t* buff, uint16_t len) { - uint16_t crc = nfca_get_crc16(buff, len); - buff[len] = (uint8_t)crc; - buff[len + 1] = (uint8_t)(crc >> 8); -} - -bool mifare_sendcmd_short( - Crypto1* crypto, - FuriHalNfcTxRxContext* tx_rx, - bool crypted, - uint32_t cmd, - uint32_t data) { - uint16_t pos; - uint8_t dcmd[4] = {cmd, data, 0x00, 0x00}; - nfca_append_crc16(dcmd, 2); - - memset(tx_rx->tx_data, 0, sizeof(tx_rx->tx_data)); - memset(tx_rx->tx_parity, 0, sizeof(tx_rx->tx_parity)); - - if(crypted) { - for(pos = 0; pos < 4; pos++) { - uint8_t res = crypto1_byte(crypto, 0x00, 0) ^ dcmd[pos]; - tx_rx->tx_data[pos] = res; - tx_rx->tx_parity[0] |= - (((crypto1_filter(crypto->odd) ^ oddparity8(dcmd[pos])) & 0x01) << (7 - pos)); - } - - tx_rx->tx_rx_type = FuriHalNfcTxRxTypeRaw; - tx_rx->tx_bits = 4 * 8; - } else { - for(pos = 0; pos < 2; pos++) { - tx_rx->tx_data[pos] = dcmd[pos]; - } - - tx_rx->tx_rx_type = FuriHalNfcTxRxTypeRxNoCrc; - tx_rx->tx_bits = 2 * 8; - } - - if(!furi_hal_nfc_tx_rx(tx_rx, 6)) return false; - - return true; -} - -bool mifare_classic_authex( - Crypto1* crypto, - FuriHalNfcTxRxContext* tx_rx, - uint32_t uid, - uint32_t blockNo, - uint32_t keyType, - uint64_t ui64Key, - bool isNested, - uint32_t* ntptr) { - uint32_t nt, ntpp; // Supplied tag nonce - uint8_t nr[4]; - - // "random" reader nonce: - nfc_util_num2bytes(prng_successor(0, 32), 4, nr); // DWT->CYCCNT - - // Transmit MIFARE_CLASSIC_AUTH - if(!mifare_sendcmd_short(crypto, tx_rx, isNested, 0x60 + (keyType & 0x01), blockNo)) { - return false; - }; - - memset(tx_rx->tx_data, 0, sizeof(tx_rx->tx_data)); - memset(tx_rx->tx_parity, 0, sizeof(tx_rx->tx_parity)); - - nt = (uint32_t)nfc_util_bytes2num(tx_rx->rx_data, 4); - - if(isNested) crypto1_reset(crypto); // deinit - - crypto1_init(crypto, ui64Key); - - if(isNested) { - nt = crypto1_word(crypto, nt ^ uid, 1) ^ nt; - } else { - crypto1_word(crypto, nt ^ uid, 0); - } - - // save Nt - if(ntptr) *ntptr = nt; - - // Generate (encrypted) nr+parity by loading it into the cipher (Nr) - tx_rx->tx_parity[0] = 0; - for(uint8_t i = 0; i < 4; i++) { - tx_rx->tx_data[i] = crypto1_byte(crypto, nr[i], 0) ^ nr[i]; - tx_rx->tx_parity[0] |= - (((crypto1_filter(crypto->odd) ^ oddparity8(nr[i])) & 0x01) << (7 - i)); - } - - nt = prng_successor(nt, 32); - - for(uint8_t i = 4; i < 8; i++) { - nt = prng_successor(nt, 8); - tx_rx->tx_data[i] = crypto1_byte(crypto, 0x00, 0) ^ (nt & 0xff); - tx_rx->tx_parity[0] |= - (((crypto1_filter(crypto->odd) ^ oddparity8(nt & 0xff)) & 0x01) << (7 - i)); - } - - tx_rx->tx_rx_type = FuriHalNfcTxRxTypeRaw; - tx_rx->tx_bits = 8 * 8; - - if(!furi_hal_nfc_tx_rx(tx_rx, 25)) { - return false; - }; - - uint32_t answer = (uint32_t)nfc_util_bytes2num(tx_rx->rx_data, 4); - - ntpp = prng_successor(nt, 32) ^ crypto1_word(crypto, 0, 0); - - if(answer != ntpp) { - return false; - } - - return true; -} - -static int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, const uint8_t* parity) { - return ((oddparity8((Nt >> 24) & 0xFF) == - ((parity[0]) ^ oddparity8((NtEnc >> 24) & 0xFF) ^ FURI_BIT(Ks1, 16))) && - (oddparity8((Nt >> 16) & 0xFF) == - ((parity[1]) ^ oddparity8((NtEnc >> 16) & 0xFF) ^ FURI_BIT(Ks1, 8))) && - (oddparity8((Nt >> 8) & 0xFF) == - ((parity[2]) ^ oddparity8((NtEnc >> 8) & 0xFF) ^ FURI_BIT(Ks1, 0)))) ? - 1 : - 0; -} - -void nonce_distance(uint32_t* msb, uint32_t* lsb) { - uint16_t x = 1, pos; - uint8_t calc_ok = 0; - - for(uint16_t i = 1; i; ++i) { - pos = (x & 0xff) << 8 | x >> 8; - - if((pos == *msb) & !(calc_ok >> 0 & 0x01)) { - *msb = i; - calc_ok |= 0x01; - } - - if((pos == *lsb) & !(calc_ok >> 1 & 0x01)) { - *lsb = i; - calc_ok |= 0x02; - } - - if(calc_ok == 0x03) { - return; - } - - x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15; - } -} - -bool validate_prng_nonce(uint32_t nonce) { - uint32_t msb = nonce >> 16; - uint32_t lsb = nonce & 0xffff; - nonce_distance(&msb, &lsb); - return ((65535 - msb + lsb) % 65535) == 16; -} - -MifareNestedNonceType nested_check_nonce_type(FuriHalNfcTxRxContext* tx_rx, uint8_t blockNo) { - uint32_t nonces[5] = {}; - uint8_t sameNonces = 0; - uint8_t hardNonces = 0; - Crypto1 crypt; - Crypto1* crypto = {&crypt}; - - for(int32_t i = 0; i < 5; i++) { - // Setup nfc poller - nfc_activate(); - furi_hal_nfc_activate_nfca(100, NULL); - - // Start communication - bool success = mifare_sendcmd_short(crypto, tx_rx, false, 0x60, blockNo); - if(!success) { - continue; - }; - - uint32_t nt = (uint32_t)nfc_util_bytes2num(tx_rx->rx_data, 4); - if(nt == 0) continue; - if(!validate_prng_nonce(nt)) hardNonces++; - nonces[i] = nt; - - nfc_deactivate(); - } - - for(int32_t i = 0; i < 5; i++) { - for(int32_t j = 0; j < 5; j++) { - if(i != j && nonces[j] && nonces[i] == nonces[j]) { - sameNonces++; - } - } - } - - if(!nonces[4]) { - return MifareNestedNonceNoTag; - } - - if(sameNonces > 3) { - return MifareNestedNonceStatic; - } - - if(hardNonces > 3) { - return MifareNestedNonceHard; - } - - return MifareNestedNonceWeak; -} - -struct nonce_info_static nested_static_nonce_attack( - FuriHalNfcTxRxContext* tx_rx, - uint8_t blockNo, - uint8_t keyType, - uint8_t targetBlockNo, - uint8_t targetKeyType, - uint64_t ui64Key) { - uint32_t cuid = 0; - Crypto1* crypto = malloc(sizeof(Crypto1)); - struct nonce_info_static r; - - r.full = false; - - // Setup nfc poller - nfc_activate(); - if(!furi_hal_nfc_activate_nfca(200, &cuid)) { - free(crypto); - return r; - } - - r.cuid = cuid; - - uint32_t nt1; - uint32_t nt_unused; - - crypto1_reset(crypto); - - mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, false, &nt1); - - if(targetKeyType == 1 && nt1 == 0x009080A2) { - r.target_nt[0] = prng_successor(nt1, 161); - r.target_nt[1] = prng_successor(nt1, 321); - } else { - r.target_nt[0] = prng_successor(nt1, 160); - r.target_nt[1] = prng_successor(nt1, 320); - } - - bool success = - mifare_sendcmd_short(crypto, tx_rx, true, 0x60 + (targetKeyType & 0x01), targetBlockNo); - - if(!success) { - free(crypto); - return r; - }; - - uint32_t nt2 = nfc_util_bytes2num(tx_rx->rx_data, 4); - r.target_ks[0] = nt2 ^ r.target_nt[0]; - - nfc_activate(); - - if(!furi_hal_nfc_activate_nfca(200, &cuid)) { - free(crypto); - return r; - } - - crypto1_reset(crypto); - - mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, false, &nt1); - - mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, true, &nt_unused); - - success = - mifare_sendcmd_short(crypto, tx_rx, true, 0x60 + (targetKeyType & 0x01), targetBlockNo); - - free(crypto); - - if(!success) { - return r; - }; - - uint32_t nt3 = (uint32_t)nfc_util_bytes2num(tx_rx->rx_data, 4); - - r.target_ks[1] = nt3 ^ r.target_nt[1]; - r.full = true; - - nfc_deactivate(); - - return r; -} - -uint32_t nested_calibrate_distance( - FuriHalNfcTxRxContext* tx_rx, - uint8_t blockNo, - uint8_t keyType, - uint64_t ui64Key, - uint32_t delay, - bool full) { - uint32_t cuid = 0; - Crypto1* crypto = malloc(sizeof(Crypto1)); - uint32_t nt1, nt2, i = 0, davg = 0, dmin = 0, dmax = 0, rtr = 0, unsuccessful_tries = 0; - uint32_t max_prng_value = full ? 65565 : 1200; - uint32_t rounds = full ? 5 : 17; // full does not require precision - uint32_t collected = 0; - - for(rtr = 0; rtr < rounds; rtr++) { - nfc_activate(); - if(!furi_hal_nfc_activate_nfca(200, &cuid)) break; - - if(!mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, false, &nt1)) { - continue; - } - - furi_delay_us(delay); - - if(!mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, true, &nt2)) { - continue; - } - - // NXP Mifare is typical around 840, but for some unlicensed/compatible mifare tag this can be 160 - uint32_t nttmp = prng_successor(nt1, 100); - - for(i = 101; i < max_prng_value; i++) { - nttmp = prng_successor(nttmp, 1); - if(nttmp == nt2) break; - } - - if(i != max_prng_value) { - if(rtr != 0) { - davg += i; - dmin = MIN(dmin, i); - dmax = MAX(dmax, i); - } else { - dmin = dmax = i; - } - - FURI_LOG_D(TAG, "Calibrating: ntdist=%lu", i); - collected++; - } else { - unsuccessful_tries++; - if(unsuccessful_tries > 12) { - free(crypto); - FURI_LOG_E( - TAG, - "Tag isn't vulnerable to nested attack (random numbers are not predictable)"); - return 0; - } - } - } - - if(collected > 1) davg = (davg + (collected - 1) / 2) / (collected - 1); - - davg = MIN(MAX(dmin, davg), dmax); - - FURI_LOG_I( - TAG, - "Calibration completed: rtr=%lu min=%lu max=%lu avg=%lu collected=%lu", - rtr, - dmin, - dmax, - davg, - collected); - - free(crypto); - - nfc_deactivate(); - - return davg; -} - -struct distance_info nested_calibrate_distance_info( - FuriHalNfcTxRxContext* tx_rx, - uint8_t blockNo, - uint8_t keyType, - uint64_t ui64Key) { - uint32_t cuid = 0; - Crypto1* crypto = malloc(sizeof(Crypto1)); - uint32_t nt1, nt2, i = 0, davg = 0, dmin = 0, dmax = 0, rtr = 0, unsuccessful_tries = 0; - struct distance_info r; - r.min_prng = 0; - r.max_prng = 0; - r.mid_prng = 0; - - for(rtr = 0; rtr < 10; rtr++) { - nfc_activate(); - if(!furi_hal_nfc_activate_nfca(200, &cuid)) break; - - mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, false, &nt1); - - mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, true, &nt2); - - // NXP Mifare is typical around 840, but for some unlicensed/compatible mifare tag this can be 160 - uint32_t nttmp = prng_successor(nt1, 1); - - for(i = 2; i < 65565; i++) { - nttmp = prng_successor(nttmp, 1); - if(nttmp == nt2) break; - } - - if(i != 65565) { - if(rtr != 0) { - davg += i; - if(dmin == 0) { - dmin = i; - } else { - dmin = MIN(dmin, i); - } - dmax = MAX(dmax, i); - } - - FURI_LOG_D(TAG, "Calibrating: ntdist=%lu", i); - } else { - unsuccessful_tries++; - if(unsuccessful_tries > 12) { - free(crypto); - - FURI_LOG_E( - TAG, - "Tag isn't vulnerable to nested attack (random numbers are not predictable)"); - - return r; - } - } - } - - if(rtr > 1) davg = (davg + (rtr - 1) / 2) / (rtr - 1); - - FURI_LOG_I( - TAG, "Calibration completed: rtr=%lu min=%lu max=%lu avg=%lu", rtr, dmin, dmax, davg); - - r.min_prng = dmin; - r.max_prng = dmax; - r.mid_prng = davg; - - free(crypto); - - nfc_deactivate(); - - return r; -} - -struct nonce_info nested_attack( - FuriHalNfcTxRxContext* tx_rx, - uint8_t blockNo, - uint8_t keyType, - uint8_t targetBlockNo, - uint8_t targetKeyType, - uint64_t ui64Key, - uint32_t distance, - uint32_t delay) { - uint32_t cuid = 0; - Crypto1* crypto = malloc(sizeof(Crypto1)); - uint8_t par_array[4] = {0x00}; - uint32_t nt1, nt2, ks1, i = 0, j = 0; - struct nonce_info r; - uint32_t dmin = distance - 2; - uint32_t dmax = distance + 2; - - r.full = false; - - for(i = 0; i < 2; i++) { // look for exactly two different nonces - r.target_nt[i] = 0; - - while(r.target_nt[i] == 0) { // continue until we have an unambiguous nonce - nfc_activate(); - if(!furi_hal_nfc_activate_nfca(200, &cuid)) { - free(crypto); - return r; - } - - r.cuid = cuid; - - mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, false, &nt1); - - furi_delay_us(delay); - - bool success = mifare_sendcmd_short( - crypto, tx_rx, true, 0x60 + (targetKeyType & 0x01), targetBlockNo); - - if(!success) continue; - - nt2 = nfc_util_bytes2num(tx_rx->rx_data, 4); - - // Parity validity check - for(j = 0; j < 4; j++) { - par_array[j] = - (oddparity8(tx_rx->rx_data[j]) != ((tx_rx->rx_parity[0] >> (7 - j)) & 0x01)); - } - - uint32_t ncount = 0; - uint32_t nttest = prng_successor(nt1, dmin - 1); - - for(j = dmin; j < dmax + 1; j++) { - nttest = prng_successor(nttest, 1); - ks1 = nt2 ^ nttest; - - if(valid_nonce(nttest, nt2, ks1, par_array)) { - if(ncount > 0) { // we are only interested in disambiguous nonces, try again - FURI_LOG_D(TAG, "Nonce#%lu: dismissed (ambiguous), ntdist=%lu", i + 1, j); - r.target_nt[i] = 0; - break; - } - - if(delay) { - // will predict later - r.target_nt[i] = nt1; - r.target_ks[i] = nt2; - } else { - r.target_nt[i] = nttest; - r.target_ks[i] = ks1; - } - - memcpy(&r.parity[i], par_array, 4); - ncount++; - - if(i == 1 && - (r.target_nt[0] == r.target_nt[1] || - r.target_ks[0] == r.target_ks[1])) { // we need two different nonces - r.target_nt[i] = 0; - FURI_LOG_D(TAG, "Nonce#2: dismissed (= nonce#1), ntdist=%lu", j); - break; - } - - FURI_LOG_D(TAG, "Nonce#%lu: valid, ntdist=%lu", i + 1, j); - } - } - - if(r.target_nt[i] == 0 && j == dmax + 1) { - FURI_LOG_D(TAG, "Nonce#%lu: dismissed (all invalid)", i + 1); - } - } - } - - if(r.target_nt[0] && r.target_nt[1]) { - r.full = true; - } - - free(crypto); - - nfc_deactivate(); - - return r; -} - -struct nonce_info_hard nested_hard_nonce_attack( - FuriHalNfcTxRxContext* tx_rx, - uint8_t blockNo, - uint8_t keyType, - uint8_t targetBlockNo, - uint8_t targetKeyType, - uint64_t ui64Key, - uint32_t* found, - uint32_t* first_byte_sum, - Stream* file_stream) { - uint32_t cuid = 0; - uint8_t same = 0; - uint64_t previous = 0; - Crypto1* crypto = malloc(sizeof(Crypto1)); - uint8_t par_array[4] = {0x00}; - struct nonce_info_hard r; - r.full = false; - r.static_encrypted = false; - - for(uint32_t i = 0; i < 8; i++) { - nfc_activate(); - if(!furi_hal_nfc_activate_nfca(200, &cuid)) { - free(crypto); - return r; - } - - r.cuid = cuid; - - if(!mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, false, NULL)) - continue; - - if(!mifare_sendcmd_short(crypto, tx_rx, true, 0x60 + (targetKeyType & 0x01), targetBlockNo)) - continue; - - uint64_t nt = nfc_util_bytes2num(tx_rx->rx_data, 4); - - for(uint32_t j = 0; j < 4; j++) { - par_array[j] = - (oddparity8(tx_rx->rx_data[j]) != ((tx_rx->rx_parity[0] >> (7 - j)) & 0x01)); - } - - uint8_t pbits = 0; - for(uint8_t j = 0; j < 4; j++) { - uint8_t p = oddparity8(tx_rx->rx_data[j]); - if(par_array[j]) { - p ^= 1; - } - pbits <<= 1; - pbits |= p; - } - - // update unique nonces - if(!found[tx_rx->rx_data[0]]) { - *first_byte_sum += evenparity32(pbits & 0x08); - found[tx_rx->rx_data[0]]++; - } - - if(nt == previous) { - same++; - } - - previous = nt; - - FuriString* row = furi_string_alloc_printf("%llu|%u\n", nt, pbits); - stream_write_string(file_stream, row); - - FURI_LOG_D(TAG, "Accured %lu/8 nonces", i + 1); - furi_string_free(row); - } - - if(same > 4) { - r.static_encrypted = true; - } - - r.full = true; - - free(crypto); - - nfc_deactivate(); - - return r; -} - -NestedCheckKeyResult nested_check_key( - FuriHalNfcTxRxContext* tx_rx, - uint8_t blockNo, - uint8_t keyType, - uint64_t ui64Key) { - uint32_t cuid = 0; - uint32_t nt; - - nfc_activate(); - if(!furi_hal_nfc_activate_nfca(200, &cuid)) return NestedCheckKeyNoTag; - - FURI_LOG_D( - TAG, "Checking %c key %012llX for block %u", !keyType ? 'A' : 'B', ui64Key, blockNo); - - Crypto1* crypto = malloc(sizeof(Crypto1)); - - bool success = - mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, false, &nt); - - free(crypto); - - nfc_deactivate(); - - return success ? NestedCheckKeyValid : NestedCheckKeyInvalid; -} - -bool nested_check_block(FuriHalNfcTxRxContext* tx_rx, uint8_t blockNo, uint8_t keyType) { - uint32_t cuid = 0; - - nfc_activate(); - if(!furi_hal_nfc_activate_nfca(200, &cuid)) return false; - - Crypto1* crypto = malloc(sizeof(Crypto1)); - - bool success = mifare_sendcmd_short(crypto, tx_rx, false, 0x60 + (keyType & 0x01), blockNo); - - free(crypto); - - nfc_deactivate(); - - return success; -} - -void nested_get_data(FuriHalNfcDevData* dev_data) { - nfc_activate(); - furi_hal_nfc_detect(dev_data, 400); - nfc_deactivate(); -} - -void nfc_activate() { - nfc_deactivate(); - - // Setup nfc poller - furi_hal_nfc_exit_sleep(); - furi_hal_nfc_ll_txrx_on(); - furi_hal_nfc_ll_poll(); - if(furi_hal_nfc_ll_set_mode( - FuriHalNfcModePollNfca, FuriHalNfcBitrate106, FuriHalNfcBitrate106) != - FuriHalNfcReturnOk) - return; - - furi_hal_nfc_ll_set_fdt_listen(FURI_HAL_NFC_LL_FDT_LISTEN_NFCA_POLLER); - furi_hal_nfc_ll_set_fdt_poll(FURI_HAL_NFC_LL_FDT_POLL_NFCA_POLLER); - furi_hal_nfc_ll_set_error_handling(FuriHalNfcErrorHandlingNfc); - furi_hal_nfc_ll_set_guard_time(FURI_HAL_NFC_LL_GT_NFCA); -} - -void nfc_deactivate() { - furi_hal_nfc_ll_txrx_off(); - furi_hal_nfc_start_sleep(); - furi_hal_nfc_sleep(); -} diff --git a/applications/external/mifare_nested/lib/nested/nested.h b/applications/external/mifare_nested/lib/nested/nested.h deleted file mode 100644 index a2b902446..000000000 --- a/applications/external/mifare_nested/lib/nested/nested.h +++ /dev/null @@ -1,118 +0,0 @@ -#pragma once - -#include -#include -#include - -#include -#include -#include - -typedef enum { - MifareNestedNonceNoTag, - MifareNestedNonceWeak, - MifareNestedNonceStatic, - MifareNestedNonceHard, -} MifareNestedNonceType; - -MifareNestedNonceType nested_check_nonce_type(FuriHalNfcTxRxContext* tx_rx, uint8_t blockNo); - -struct nonce_info_static { - uint32_t cuid; - uint32_t target_nt[2]; - uint32_t target_ks[2]; - bool full; -}; - -struct nonce_info_hard { - uint32_t cuid; - bool static_encrypted; - bool full; -}; - -struct nonce_info { - uint32_t cuid; - uint32_t target_nt[2]; - uint32_t target_ks[2]; - uint8_t parity[2][4]; - bool full; -}; - -struct distance_info { - uint32_t min_prng; - uint32_t max_prng; - uint32_t mid_prng; -}; - -struct nonce_info_static nested_static_nonce_attack( - FuriHalNfcTxRxContext* tx_rx, - uint8_t blockNo, - uint8_t keyType, - uint8_t targetBlockNo, - uint8_t targetKeyType, - uint64_t ui64Key); - -struct nonce_info nested_attack( - FuriHalNfcTxRxContext* tx_rx, - uint8_t blockNo, - uint8_t keyType, - uint8_t targetBlockNo, - uint8_t targetKeyType, - uint64_t ui64Key, - uint32_t distance, - uint32_t delay); - -struct nonce_info_hard nested_hard_nonce_attack( - FuriHalNfcTxRxContext* tx_rx, - uint8_t blockNo, - uint8_t keyType, - uint8_t targetBlockNo, - uint8_t targetKeyType, - uint64_t ui64Key, - uint32_t* found, - uint32_t* first_byte_sum, - Stream* file_stream); - -uint32_t nested_calibrate_distance( - FuriHalNfcTxRxContext* tx_rx, - uint8_t blockNo, - uint8_t keyType, - uint64_t ui64Key, - uint32_t delay, - bool full); - -struct distance_info nested_calibrate_distance_info( - FuriHalNfcTxRxContext* tx_rx, - uint8_t blockNo, - uint8_t keyType, - uint64_t ui64Key); - -typedef enum { - NestedCheckKeyNoTag, - NestedCheckKeyValid, - NestedCheckKeyInvalid, -} NestedCheckKeyResult; - -NestedCheckKeyResult nested_check_key( - FuriHalNfcTxRxContext* tx_rx, - uint8_t blockNo, - uint8_t keyType, - uint64_t ui64Key); - -bool nested_check_block(FuriHalNfcTxRxContext* tx_rx, uint8_t blockNo, uint8_t keyType); - -void nested_get_data(); - -bool mifare_classic_authex( - Crypto1* crypto, - FuriHalNfcTxRxContext* tx_rx, - uint32_t uid, - uint32_t blockNo, - uint32_t keyType, - uint64_t ui64Key, - bool isNested, - uint32_t* ntptr); - -void nfc_activate(); - -void nfc_deactivate(); diff --git a/applications/external/mifare_nested/lib/parity/parity.c b/applications/external/mifare_nested/lib/parity/parity.c deleted file mode 100644 index c8e2f807e..000000000 --- a/applications/external/mifare_nested/lib/parity/parity.c +++ /dev/null @@ -1,71 +0,0 @@ -#include "parity.h" - -uint32_t __paritysi2(uint32_t a) { - uint32_t x = (uint32_t)a; - x ^= x >> 16; - x ^= x >> 8; - x ^= x >> 4; - return (0x6996 >> (x & 0xF)) & 1; -} - -static const uint8_t g_odd_byte_parity[256] = { - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, - 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, - 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, - 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, - 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, - 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, - 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1}; - -#define ODD_PARITY8(x) \ - { g_odd_byte_parity[x] } -#define EVEN_PARITY8(x) \ - { !g_odd_byte_parity[x] } - -uint8_t oddparity8(const uint8_t x) { - return g_odd_byte_parity[x]; -} - -uint8_t evenparity8(const uint8_t x) { - return !g_odd_byte_parity[x]; -} - -uint8_t evenparity16(uint16_t x) { -#if !defined __GNUC__ - x ^= x >> 8; - return EVEN_PARITY8(x); -#else - return (__builtin_parity(x) & 0xFF); -#endif -} - -uint8_t oddparity16(uint16_t x) { -#if !defined __GNUC__ - x ^= x >> 8; - return ODD_PARITY8(x); -#else - return !__builtin_parity(x); -#endif -} - -uint8_t evenparity32(uint32_t x) { -#if !defined __GNUC__ - x ^= x >> 16; - x ^= x >> 8; - return EVEN_PARITY8(x); -#else - return (__builtin_parity(x) & 0xFF); -#endif -} - -uint8_t oddparity32(uint32_t x) { -#if !defined __GNUC__ - x ^= x >> 16; - x ^= x >> 8; - return ODD_PARITY8(x); -#else - return !__builtin_parity(x); -#endif -} \ No newline at end of file diff --git a/applications/external/mifare_nested/lib/parity/parity.h b/applications/external/mifare_nested/lib/parity/parity.h deleted file mode 100644 index 16648afa1..000000000 --- a/applications/external/mifare_nested/lib/parity/parity.h +++ /dev/null @@ -1,10 +0,0 @@ -#include "stdint.h" - -uint8_t oddparity8(const uint8_t x); -uint8_t evenparity8(const uint8_t x); - -uint8_t evenparity16(uint16_t x); -uint8_t oddparity16(uint16_t x); - -uint8_t evenparity32(uint32_t x); -uint8_t oddparity32(uint32_t x); \ No newline at end of file diff --git a/applications/external/mifare_nested/mifare_nested.c b/applications/external/mifare_nested/mifare_nested.c deleted file mode 100644 index bb6947a91..000000000 --- a/applications/external/mifare_nested/mifare_nested.c +++ /dev/null @@ -1,409 +0,0 @@ -#include "mifare_nested_i.h" -#include - -bool mifare_nested_custom_event_callback(void* context, uint32_t event) { - furi_assert(context); - MifareNested* mifare_nested = context; - return scene_manager_handle_custom_event(mifare_nested->scene_manager, event); -} - -bool mifare_nested_back_event_callback(void* context) { - furi_assert(context); - MifareNested* mifare_nested = context; - return scene_manager_handle_back_event(mifare_nested->scene_manager); -} - -void mifare_nested_tick_event_callback(void* context) { - furi_assert(context); - MifareNested* mifare_nested = context; - scene_manager_handle_tick_event(mifare_nested->scene_manager); -} - -void mifare_nested_show_loading_popup(void* context, bool show) { - MifareNested* mifare_nested = context; - TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME); - - if(show) { - // Raise timer priority so that animations can play - vTaskPrioritySet(timer_task, configMAX_PRIORITIES - 1); - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewLoading); - } else { - // Restore default timer priority - vTaskPrioritySet(timer_task, configTIMER_TASK_PRIORITY); - } -} - -NestedState* collection_alloc() { - NestedState* nested = malloc(sizeof(NestedState)); - nested->view = view_alloc(); - view_allocate_model(nested->view, ViewModelTypeLocking, sizeof(NestedAttackViewModel)); - with_view_model( - nested->view, - NestedAttackViewModel * model, - { - model->header = furi_string_alloc(); - furi_string_set(model->header, "Collecting nonces"); - model->keys_count = 0; - model->hardnested_states = 0; - model->lost_tag = false; - model->calibrating = false; - model->need_prediction = false; - model->hardnested = false; - }, - false); - - return nested; -} - -CheckKeysState* check_keys_alloc() { - CheckKeysState* state = malloc(sizeof(CheckKeysState)); - state->view = view_alloc(); - view_allocate_model(state->view, ViewModelTypeLocking, sizeof(CheckKeysViewModel)); - with_view_model( - state->view, - CheckKeysViewModel * model, - { - model->header = furi_string_alloc(); - furi_string_set(model->header, "Checking keys"); - model->lost_tag = false; - }, - false); - - return state; -} - -static void nested_draw_callback(Canvas* canvas, void* model) { - NestedAttackViewModel* m = model; - - if(m->lost_tag) { - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 64, 4, AlignCenter, AlignTop, "Lost the tag!"); - canvas_set_font(canvas, FontSecondary); - elements_multiline_text_aligned( - canvas, 64, 23, AlignCenter, AlignTop, "Make sure the tag is\npositioned correctly."); - } else if(m->calibrating) { - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 64, 4, AlignCenter, AlignTop, "Calibrating..."); - canvas_set_font(canvas, FontSecondary); - if(!m->need_prediction) { - elements_multiline_text_aligned( - canvas, 64, 23, AlignCenter, AlignTop, "Don't touch or move\nFlipper/Tag!"); - } else { - elements_multiline_text_aligned( - canvas, 64, 18, AlignCenter, AlignTop, "Don't touch or move tag!"); - canvas_set_font(canvas, FontPrimary); - elements_multiline_text_aligned( - canvas, 64, 30, AlignCenter, AlignTop, "Calibration will take\nmore time"); - } - } else if(m->hardnested) { - char draw_str[32] = {}; - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned( - canvas, 64, 2, AlignCenter, AlignTop, furi_string_get_cstr(m->header)); - canvas_set_font(canvas, FontSecondary); - - float progress = - m->keys_count == 0 ? 0 : (float)(m->nonces_collected) / (float)(m->keys_count); - - if(progress > 1.0) { - progress = 1.0; - } - - elements_progress_bar(canvas, 5, 15, 120, progress); - canvas_set_font(canvas, FontSecondary); - snprintf( - draw_str, - sizeof(draw_str), - "Nonces collected: %lu/%lu", - m->nonces_collected, - m->keys_count); - canvas_draw_str_aligned(canvas, 1, 28, AlignLeft, AlignTop, draw_str); - snprintf(draw_str, sizeof(draw_str), "States found: %lu/256", m->hardnested_states); - canvas_draw_str_aligned(canvas, 1, 40, AlignLeft, AlignTop, draw_str); - } else { - char draw_str[32] = {}; - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned( - canvas, 64, 2, AlignCenter, AlignTop, furi_string_get_cstr(m->header)); - canvas_set_font(canvas, FontSecondary); - - float progress = - m->keys_count == 0 ? 0 : (float)(m->nonces_collected) / (float)(m->keys_count); - - if(progress > 1.0) { - progress = 1.0; - } - - elements_progress_bar(canvas, 5, 15, 120, progress); - canvas_set_font(canvas, FontSecondary); - snprintf( - draw_str, - sizeof(draw_str), - "Nonces collected: %lu/%lu", - m->nonces_collected, - m->keys_count); - canvas_draw_str_aligned(canvas, 1, 28, AlignLeft, AlignTop, draw_str); - } - - elements_button_center(canvas, "Stop"); -} - -static void check_keys_draw_callback(Canvas* canvas, void* model) { - CheckKeysViewModel* m = model; - - if(m->lost_tag) { - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 64, 4, AlignCenter, AlignTop, "Lost the tag!"); - canvas_set_font(canvas, FontSecondary); - elements_multiline_text_aligned( - canvas, 64, 23, AlignCenter, AlignTop, "Make sure the tag is\npositioned correctly."); - } else if(m->processing_keys) { - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 64, 4, AlignCenter, AlignTop, "Processing keys..."); - canvas_set_font(canvas, FontSecondary); - elements_multiline_text_aligned( - canvas, 64, 23, AlignCenter, AlignTop, "Checking which keys you\nalready have..."); - } else { - char draw_str[32] = {}; - char draw_sub_str[32] = {}; - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned( - canvas, 64, 2, AlignCenter, AlignTop, furi_string_get_cstr(m->header)); - canvas_set_font(canvas, FontSecondary); - - float progress = m->keys_count == 0 ? 0 : - (float)(m->keys_checked) / (float)(m->keys_count); - - if(progress > 1.0) { - progress = 1.0; - } - - elements_progress_bar(canvas, 5, 15, 120, progress); - canvas_set_font(canvas, FontSecondary); - snprintf( - draw_str, sizeof(draw_str), "Keys checked: %lu/%lu", m->keys_checked, m->keys_count); - canvas_draw_str_aligned(canvas, 1, 28, AlignLeft, AlignTop, draw_str); - snprintf( - draw_sub_str, - sizeof(draw_sub_str), - "Keys found: %lu/%lu", - m->keys_found, - m->keys_total); - canvas_draw_str_aligned(canvas, 1, 40, AlignLeft, AlignTop, draw_sub_str); - } - - elements_button_center(canvas, "Stop"); -} - -static bool nested_input_callback(InputEvent* event, void* context) { - MifareNested* mifare_nested = context; - - bool consumed = false; - - if(event->type == InputTypeShort && (event->key == InputKeyBack || event->key == InputKeyOk)) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - - return consumed; -} - -MifareNested* mifare_nested_alloc() { - MifareNested* mifare_nested = malloc(sizeof(MifareNested)); - - mifare_nested->worker = mifare_nested_worker_alloc(); - mifare_nested->view_dispatcher = view_dispatcher_alloc(); - mifare_nested->scene_manager = - scene_manager_alloc(&mifare_nested_scene_handlers, mifare_nested); - view_dispatcher_enable_queue(mifare_nested->view_dispatcher); - view_dispatcher_set_event_callback_context(mifare_nested->view_dispatcher, mifare_nested); - view_dispatcher_set_custom_event_callback( - mifare_nested->view_dispatcher, mifare_nested_custom_event_callback); - view_dispatcher_set_navigation_event_callback( - mifare_nested->view_dispatcher, mifare_nested_back_event_callback); - view_dispatcher_set_tick_event_callback( - mifare_nested->view_dispatcher, mifare_nested_tick_event_callback, 100); - - // Nfc device - mifare_nested->nfc_dev = nfc_device_alloc(); - - // Open GUI record - mifare_nested->gui = furi_record_open(RECORD_GUI); - view_dispatcher_attach_to_gui( - mifare_nested->view_dispatcher, mifare_nested->gui, ViewDispatcherTypeFullscreen); - - // Open Notification record - mifare_nested->notifications = furi_record_open(RECORD_NOTIFICATION); - - // Submenu - mifare_nested->submenu = submenu_alloc(); - view_dispatcher_add_view( - mifare_nested->view_dispatcher, - MifareNestedViewMenu, - submenu_get_view(mifare_nested->submenu)); - - // Popup - mifare_nested->popup = popup_alloc(); - view_dispatcher_add_view( - mifare_nested->view_dispatcher, - MifareNestedViewPopup, - popup_get_view(mifare_nested->popup)); - - // Loading - mifare_nested->loading = loading_alloc(); - view_dispatcher_add_view( - mifare_nested->view_dispatcher, - MifareNestedViewLoading, - loading_get_view(mifare_nested->loading)); - - // Text Input - mifare_nested->text_input = text_input_alloc(); - view_dispatcher_add_view( - mifare_nested->view_dispatcher, - MifareNestedViewTextInput, - text_input_get_view(mifare_nested->text_input)); - - // Custom Widget - mifare_nested->widget = widget_alloc(); - view_dispatcher_add_view( - mifare_nested->view_dispatcher, - MifareNestedViewWidget, - widget_get_view(mifare_nested->widget)); - - // Variable Item List - mifare_nested->variable_item_list = variable_item_list_alloc(); - view_dispatcher_add_view( - mifare_nested->view_dispatcher, - MifareNestedViewVariableList, - variable_item_list_get_view(mifare_nested->variable_item_list)); - - // Nested attack state - NestedState* plugin_state = collection_alloc(); - view_set_context(plugin_state->view, mifare_nested); - mifare_nested->nested_state = plugin_state; - view_dispatcher_add_view( - mifare_nested->view_dispatcher, MifareNestedViewCollecting, plugin_state->view); - - // Check keys attack state - CheckKeysState* keys_state = check_keys_alloc(); - view_set_context(keys_state->view, mifare_nested); - mifare_nested->keys_state = keys_state; - view_dispatcher_add_view( - mifare_nested->view_dispatcher, MifareNestedViewCheckKeys, keys_state->view); - - KeyInfo_t* key_info = malloc(sizeof(KeyInfo_t)); - mifare_nested->keys = key_info; - - MifareNestedSettings* settings = malloc(sizeof(MifareNestedSettings)); - settings->only_hardnested = false; - mifare_nested->settings = settings; - - view_set_draw_callback(plugin_state->view, nested_draw_callback); - view_set_input_callback(plugin_state->view, nested_input_callback); - - view_set_draw_callback(keys_state->view, check_keys_draw_callback); - view_set_input_callback(keys_state->view, nested_input_callback); - - mifare_nested->collecting_type = MifareNestedWorkerStateReady; - mifare_nested->run = NestedRunIdle; - - return mifare_nested; -} - -void mifare_nested_free(MifareNested* mifare_nested) { - furi_assert(mifare_nested); - - // Nfc device - nfc_device_free(mifare_nested->nfc_dev); - - // Submenu - view_dispatcher_remove_view(mifare_nested->view_dispatcher, MifareNestedViewMenu); - submenu_free(mifare_nested->submenu); - - // Popup - view_dispatcher_remove_view(mifare_nested->view_dispatcher, MifareNestedViewPopup); - popup_free(mifare_nested->popup); - - // Loading - view_dispatcher_remove_view(mifare_nested->view_dispatcher, MifareNestedViewLoading); - loading_free(mifare_nested->loading); - - // TextInput - view_dispatcher_remove_view(mifare_nested->view_dispatcher, MifareNestedViewTextInput); - text_input_free(mifare_nested->text_input); - - // Custom Widget - view_dispatcher_remove_view(mifare_nested->view_dispatcher, MifareNestedViewWidget); - widget_free(mifare_nested->widget); - - // Variable Item List - view_dispatcher_remove_view(mifare_nested->view_dispatcher, MifareNestedViewVariableList); - variable_item_list_free(mifare_nested->variable_item_list); - - // Nested - view_dispatcher_remove_view(mifare_nested->view_dispatcher, MifareNestedViewCollecting); - - // Check keys - view_dispatcher_remove_view(mifare_nested->view_dispatcher, MifareNestedViewCheckKeys); - - // Nonces states - free(mifare_nested->nonces); - free(mifare_nested->nested_state); - - // Keys - free(mifare_nested->keys); - - // Settings - free(mifare_nested->settings); - - // Worker - mifare_nested_worker_stop(mifare_nested->worker); - mifare_nested_worker_free(mifare_nested->worker); - - // View Dispatcher - view_dispatcher_free(mifare_nested->view_dispatcher); - - // Scene Manager - scene_manager_free(mifare_nested->scene_manager); - - // GUI - furi_record_close(RECORD_GUI); - mifare_nested->gui = NULL; - - // Notifications - furi_record_close(RECORD_NOTIFICATION); - mifare_nested->notifications = NULL; - - free(mifare_nested); -} - -void mifare_nested_blink_start(MifareNested* mifare_nested) { - notification_message(mifare_nested->notifications, &mifare_nested_sequence_blink_start_blue); -} - -void mifare_nested_blink_calibration_start(MifareNested* mifare_nested) { - notification_message( - mifare_nested->notifications, &mifare_nested_sequence_blink_start_magenta); -} - -void mifare_nested_blink_nonce_collection_start(MifareNested* mifare_nested) { - notification_message(mifare_nested->notifications, &mifare_nested_sequence_blink_start_yellow); -} - -void mifare_nested_blink_stop(MifareNested* mifare_nested) { - notification_message(mifare_nested->notifications, &mifare_nested_sequence_blink_stop); -} - -int32_t mifare_nested_app(void* p) { - UNUSED(p); - - MifareNested* mifare_nested = mifare_nested_alloc(); - - scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneStart); - - view_dispatcher_run(mifare_nested->view_dispatcher); - - mifare_nested_free(mifare_nested); - - return 0; -} diff --git a/applications/external/mifare_nested/mifare_nested.h b/applications/external/mifare_nested/mifare_nested.h deleted file mode 100644 index a59a5b8ca..000000000 --- a/applications/external/mifare_nested/mifare_nested.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -typedef struct MifareNested MifareNested; diff --git a/applications/external/mifare_nested/mifare_nested_i.h b/applications/external/mifare_nested/mifare_nested_i.h deleted file mode 100644 index 324328b44..000000000 --- a/applications/external/mifare_nested/mifare_nested_i.h +++ /dev/null @@ -1,182 +0,0 @@ -#pragma once -#include "mifare_nested.h" -#include "mifare_nested_worker.h" -#include "lib/nested/nested.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "scenes/mifare_nested_scene.h" -#include -#include -#include -#include -#include -#include "mifare_nested_icons.h" -#include - -#define NESTED_VERSION_APP "1.5.2" -#define NESTED_GITHUB_LINK "https://github.com/AloneLiberty/FlipperNested" -#define NESTED_RECOVER_KEYS_GITHUB_LINK "https://github.com/AloneLiberty/FlipperNestedRecovery" -#define NESTED_NONCE_FORMAT_VERSION "3" -#define NESTED_AUTHOR "@AloneLiberty (t.me/libertydev)" - -enum MifareNestedCustomEvent { - // Reserve first 100 events for button types and indexes, starting from 0 - MifareNestedCustomEventReserved = 100, - - MifareNestedCustomEventViewExit, - MifareNestedCustomEventWorkerExit, - MifareNestedCustomEventByteInputDone, - MifareNestedCustomEventTextInputDone, - MifareNestedCustomEventSceneSettingLock -}; - -typedef void (*NestedCallback)(void* context); - -typedef struct { - FuriMutex* mutex; - FuriMessageQueue* event_queue; - ViewPort* view_port; - View* view; - NestedCallback callback; - void* context; -} NestedState; - -typedef void (*CheckKeysCallback)(void* context); - -typedef struct { - FuriMutex* mutex; - FuriMessageQueue* event_queue; - ViewPort* view_port; - View* view; - CheckKeysCallback callback; - void* context; -} CheckKeysState; - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef struct { - EventType type; - InputEvent input; -} PluginEvent; - -typedef struct { - bool only_hardnested; -} MifareNestedSettings; - -typedef enum { NestedRunIdle, NestedRunCheckKeys, NestedRunAttack } NestedRunNext; - -struct MifareNested { - MifareNestedWorker* worker; - ViewDispatcher* view_dispatcher; - Gui* gui; - NotificationApp* notifications; - SceneManager* scene_manager; - NfcDevice* nfc_dev; - VariableItemList* variable_item_list; - MifareNestedSettings* settings; - FuriString* text_box_store; - - // Common Views - Submenu* submenu; - Popup* popup; - Loading* loading; - TextInput* text_input; - Widget* widget; - - NonceList_t* nonces; - KeyInfo_t* keys; - - NestedState* nested_state; - CheckKeysState* keys_state; - SaveNoncesResult_t* save_state; - - MifareNestedWorkerState collecting_type; - - NestedRunNext run; -}; - -typedef enum { - MifareNestedViewMenu, - MifareNestedViewPopup, - MifareNestedViewLoading, - MifareNestedViewTextInput, - MifareNestedViewWidget, - MifareNestedViewVariableList, - MifareNestedViewCollecting, - MifareNestedViewCheckKeys, -} MifareNestedView; - -typedef struct { - FuriString* header; - uint32_t keys_count; - uint32_t nonces_collected; - uint32_t hardnested_states; - bool lost_tag; - bool calibrating; - bool need_prediction; - bool hardnested; -} NestedAttackViewModel; - -typedef struct { - FuriString* header; - uint32_t keys_count; - uint32_t keys_checked; - uint32_t keys_found; - uint32_t keys_total; - bool lost_tag; - bool processing_keys; -} CheckKeysViewModel; - -static const NotificationSequence mifare_nested_sequence_blink_start_blue = { - &message_blink_start_10, - &message_blink_set_color_blue, - &message_do_not_reset, - NULL, -}; - -static const NotificationSequence mifare_nested_sequence_blink_start_magenta = { - &message_blink_start_10, - &message_blink_set_color_magenta, - &message_do_not_reset, - NULL, -}; - -static const NotificationSequence mifare_nested_sequence_blink_start_yellow = { - &message_blink_start_10, - &message_blink_set_color_yellow, - &message_do_not_reset, - NULL, -}; - -static const NotificationSequence mifare_nested_sequence_blink_stop = { - &message_blink_stop, - NULL, -}; - -MifareNested* mifare_nested_alloc(); - -void mifare_nested_text_store_set(MifareNested* mifare_nested, const char* text, ...); - -void mifare_nested_text_store_clear(MifareNested* mifare_nested); - -void mifare_nested_blink_start(MifareNested* mifare_nested); - -void mifare_nested_blink_calibration_start(MifareNested* mifare_nested); - -void mifare_nested_blink_nonce_collection_start(MifareNested* mifare_nested); - -void mifare_nested_blink_stop(MifareNested* mifare_nested); - -void mifare_nested_show_loading_popup(void* context, bool show); diff --git a/applications/external/mifare_nested/mifare_nested_worker.c b/applications/external/mifare_nested/mifare_nested_worker.c deleted file mode 100644 index 0b8097653..000000000 --- a/applications/external/mifare_nested/mifare_nested_worker.c +++ /dev/null @@ -1,1713 +0,0 @@ -#include "mifare_nested_worker_i.h" - -#include "lib/nested/nested.h" -#include "lib/parity/parity.h" -#include - -#include -#include -#include -#include "string.h" -#include -#include - -#define TAG "MifareNestedWorker" - -// possible sum property values -static uint16_t sums[] = - {0, 32, 56, 64, 80, 96, 104, 112, 120, 128, 136, 144, 152, 160, 176, 192, 200, 224, 256}; - -void mifare_nested_worker_change_state( - MifareNestedWorker* mifare_nested_worker, - MifareNestedWorkerState state) { - furi_assert(mifare_nested_worker); - - mifare_nested_worker->state = state; -} - -MifareNestedWorker* mifare_nested_worker_alloc() { - MifareNestedWorker* mifare_nested_worker = malloc(sizeof(MifareNestedWorker)); - - // Worker thread attributes - mifare_nested_worker->thread = furi_thread_alloc_ex( - "MifareNestedWorker", 8192, mifare_nested_worker_task, mifare_nested_worker); - - mifare_nested_worker->callback = NULL; - mifare_nested_worker->context = NULL; - - mifare_nested_worker_change_state(mifare_nested_worker, MifareNestedWorkerStateReady); - - return mifare_nested_worker; -} - -void mifare_nested_worker_free(MifareNestedWorker* mifare_nested_worker) { - furi_assert(mifare_nested_worker); - - furi_thread_free(mifare_nested_worker->thread); - free(mifare_nested_worker); -} - -void mifare_nested_worker_stop(MifareNestedWorker* mifare_nested_worker) { - furi_assert(mifare_nested_worker); - - mifare_nested_worker_change_state(mifare_nested_worker, MifareNestedWorkerStateStop); - furi_thread_join(mifare_nested_worker->thread); -} - -void mifare_nested_worker_start( - MifareNestedWorker* mifare_nested_worker, - MifareNestedWorkerState state, - NfcDeviceData* dev_data, - MifareNestedWorkerCallback callback, - void* context) { - furi_assert(mifare_nested_worker); - furi_assert(dev_data); - - mifare_nested_worker->callback = callback; - mifare_nested_worker->context = context; - mifare_nested_worker->dev_data = dev_data; - mifare_nested_worker_change_state(mifare_nested_worker, state); - furi_thread_start(mifare_nested_worker->thread); -} - -int32_t mifare_nested_worker_task(void* context) { - MifareNestedWorker* mifare_nested_worker = context; - - if(mifare_nested_worker->state == MifareNestedWorkerStateCheck) { - mifare_nested_worker_check(mifare_nested_worker); - } else if(mifare_nested_worker->state == MifareNestedWorkerStateCollectingStatic) { - mifare_nested_worker_collect_nonces_static(mifare_nested_worker); - } else if(mifare_nested_worker->state == MifareNestedWorkerStateCollecting) { - mifare_nested_worker_collect_nonces(mifare_nested_worker); - } else if(mifare_nested_worker->state == MifareNestedWorkerStateCollectingHard) { - mifare_nested_worker_collect_nonces_hard(mifare_nested_worker); - } else if(mifare_nested_worker->state == MifareNestedWorkerStateValidating) { - mifare_nested_worker_check_keys(mifare_nested_worker); - } - - mifare_nested_worker_change_state(mifare_nested_worker, MifareNestedWorkerStateReady); - - return 0; -} - -void mifare_nested_worker_write_uid_string(FuriHalNfcDevData* data, FuriString* string) { - uint8_t* uid = data->uid; - uint8_t uid_len = data->uid_len; - - for(size_t i = 0; i < uid_len; i++) { - uint8_t uid_part = uid[i]; - furi_string_cat_printf(string, "%02X", uid_part); - } -} - -void mifare_nested_worker_get_key_cache_file_path(FuriHalNfcDevData* data, FuriString* file_path) { - furi_string_set(file_path, EXT_PATH("nfc/.cache") "/"); - - mifare_nested_worker_write_uid_string(data, file_path); - - furi_string_cat_printf(file_path, ".keys"); -} - -void mifare_nested_worker_get_nonces_file_path(FuriHalNfcDevData* data, FuriString* file_path) { - furi_string_set(file_path, NESTED_FOLDER "/"); - - mifare_nested_worker_write_uid_string(data, file_path); - - furi_string_cat_printf(file_path, ".nonces"); -} - -void mifare_nested_worker_get_found_keys_file_path(FuriHalNfcDevData* data, FuriString* file_path) { - furi_string_set(file_path, NESTED_FOLDER "/"); - - mifare_nested_worker_write_uid_string(data, file_path); - - furi_string_cat_printf(file_path, ".keys"); -} - -void mifare_nested_worker_get_hardnested_folder_path( - FuriHalNfcDevData* data, - FuriString* file_path) { - furi_string_set(file_path, NESTED_FOLDER "/"); - - mifare_nested_worker_write_uid_string(data, file_path); -} - -void mifare_nested_worker_get_hardnested_file_path( - FuriHalNfcDevData* data, - FuriString* file_path, - uint8_t sector, - uint8_t key_type) { - mifare_nested_worker_get_hardnested_folder_path(data, file_path); - - furi_string_cat_printf(file_path, "/%u_%u.nonces", sector, key_type); -} - -uint8_t mifare_nested_worker_get_block_by_sector(uint8_t sector) { - furi_assert(sector < 40); - if(sector < 32) { - return (sector * 4) + 3; - } else { - return 32 * 4 + (sector - 32) * 16 + 15; - } -} - -static MfClassicSectorTrailer* - mifare_nested_worker_get_sector_trailer_by_sector(MfClassicData* data, uint8_t sector) { - return (MfClassicSectorTrailer*)data->block[mifare_nested_worker_get_block_by_sector(sector)] - .value; -} - -bool mifare_nested_worker_read_key_cache(FuriHalNfcDevData* data, MfClassicData* mf_data) { - Storage* storage = furi_record_open(RECORD_STORAGE); - FuriString* temp_str = furi_string_alloc(); - mifare_nested_worker_get_key_cache_file_path(data, temp_str); - FlipperFormat* file = flipper_format_file_alloc(storage); - bool load_success = false; - uint32_t sector_count = 0; - - do { - if(storage_common_stat(storage, furi_string_get_cstr(temp_str), NULL) != FSE_OK) break; - - if(!flipper_format_file_open_existing(file, furi_string_get_cstr(temp_str))) break; - - uint32_t version = 0; - - if(!flipper_format_read_header(file, temp_str, &version)) break; - if(furi_string_cmp_str(temp_str, "Flipper NFC keys")) break; - - if(version != 1) break; - - if(!flipper_format_read_string(file, "Mifare Classic type", temp_str)) break; - - if(!furi_string_cmp(temp_str, "1K")) { - mf_data->type = MfClassicType1k; - sector_count = 16; - } else if(!furi_string_cmp(temp_str, "4K")) { - mf_data->type = MfClassicType4k; - sector_count = 40; - } else if(!furi_string_cmp(temp_str, "MINI")) { - mf_data->type = MfClassicTypeMini; - sector_count = 5; - } else { - break; - } - - if(!flipper_format_read_hex_uint64(file, "Key A map", &mf_data->key_a_mask, 1)) break; - if(!flipper_format_read_hex_uint64(file, "Key B map", &mf_data->key_b_mask, 1)) break; - - bool key_read_success = true; - - for(size_t i = 0; (i < sector_count) && (key_read_success); i++) { - MfClassicSectorTrailer* sec_tr = - mifare_nested_worker_get_sector_trailer_by_sector(mf_data, i); - - if(FURI_BIT(mf_data->key_a_mask, i)) { - furi_string_printf(temp_str, "Key A sector %d", i); - key_read_success = flipper_format_read_hex( - file, furi_string_get_cstr(temp_str), sec_tr->key_a, 6); - } - - if(!key_read_success) break; - - if(FURI_BIT(mf_data->key_b_mask, i)) { - furi_string_printf(temp_str, "Key B sector %d", i); - key_read_success = flipper_format_read_hex( - file, furi_string_get_cstr(temp_str), sec_tr->key_b, 6); - } - } - - load_success = key_read_success; - } while(false); - - furi_string_free(temp_str); - flipper_format_free(file); - - return load_success; -} - -bool hex_char_to_hex_nibble(char c, uint8_t* nibble) { - if((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')) { - if(c <= '9') { - *nibble = c - '0'; - } else if(c <= 'F') { - *nibble = c - 'A' + 10; - } else { - *nibble = c - 'a' + 10; - } - return true; - } else { - return false; - } -} - -bool hex_char_to_uint8(char hi, char low, uint8_t* value) { - uint8_t hi_nibble_value, low_nibble_value; - - if(hex_char_to_hex_nibble(hi, &hi_nibble_value) && - hex_char_to_hex_nibble(low, &low_nibble_value)) { - *value = (hi_nibble_value << 4) | low_nibble_value; - return true; - } else { - return false; - } -} - -void free_nonces(NonceList_t* nonces, uint8_t sector_count, uint8_t tries_count) { - for(uint8_t sector = 0; sector < sector_count; sector++) { - for(uint8_t key_type = 0; key_type < 2; key_type++) { - for(uint8_t tries = 0; tries < tries_count; tries++) { - free(nonces->nonces[sector][key_type][tries]); - } - } - } -} - -MfClassicType mifare_nested_worker_get_tag_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) { - UNUSED(ATQA1); - if((ATQA0 == 0x44 || ATQA0 == 0x04)) { - if((SAK == 0x08 || SAK == 0x88)) { - return MfClassicType1k; - } else if(SAK == 0x09) { - return MfClassicTypeMini; - } - } else if((ATQA0 == 0x01) && (ATQA1 == 0x0F) && (SAK == 0x01)) { - //skylanders support - return MfClassicType1k; - } else if((ATQA0 == 0x42 || ATQA0 == 0x02) && (SAK == 0x18)) { - return MfClassicType4k; - } - return MfClassicType1k; -} - -uint32_t mifare_nested_worker_predict_delay( - FuriHalNfcTxRxContext* tx_rx, - uint8_t blockNo, - uint8_t keyType, - uint64_t ui64Key, - uint32_t tries, - MifareNestedWorker* mifare_nested_worker) { - uint32_t cuid = 0; - Crypto1* crypto = malloc(sizeof(Crypto1)); - uint32_t nt1, nt2, i = 0, previous = 0, prng_delay = 0, zero_prng_value = 65565, repeat = 0; - - if(tries > 25) { - free(crypto); - return 2; // Too many tries, fallback to hardnested - } - - // This part of attack is my attempt to implement it on Flipper. - // Check README.md for more info - - // First, we find RPNG rounds per 1000 us - for(uint32_t rtr = 0; rtr < 25; rtr++) { - if(mifare_nested_worker->state != MifareNestedWorkerStateCollecting) { - free(crypto); - return 1; - } - - nfc_activate(); - if(!furi_hal_nfc_activate_nfca(200, &cuid)) break; - - mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, false, &nt1); - - furi_delay_us(rtr * 1000); - - mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, true, &nt2); - - // Searching for delay, where PRNG will be near 800 - uint32_t nttmp = prng_successor(nt1, 100); - - for(i = 101; i < 65565; i++) { - nttmp = prng_successor(nttmp, 1); - if(nttmp == nt2) break; - } - - if(!rtr) { - zero_prng_value = i; - } - - if(previous && i > previous && i != 65565) { - if(!prng_delay) { - prng_delay = i - previous; - } else if(prng_delay - 100 > i - previous && prng_delay + 100 < i - previous) { - prng_delay += i - previous; - prng_delay /= 2; - } - } - - previous = i; - - FURI_LOG_D(TAG, "Calibrating: ntdist=%lu, delay=%lu", i, rtr * 1000); - - // Let's hope... - if(i > 810 && i < 840) { - free(crypto); - return rtr * 1000; - } - } - - FURI_LOG_D(TAG, "PRNG timing: growth ratio per 1000 us = %lu", prng_delay); - - // Next, we try to calculate time until PRNG near 800 with more perfect timing - // Mifare Classic (weak) RPNG repeats every 65565 PRNG cycles - - if(zero_prng_value == 65565) { - free(crypto); - // PRNG isn't pretictable - return 1; - } - - uint32_t cycles_to_reset = (65565 - zero_prng_value) / prng_delay; - - uint32_t limit = 7; - - for(uint32_t rtr = cycles_to_reset - 1; rtr < cycles_to_reset + limit; rtr++) { - for(uint32_t rtz = 0; rtz < 100; rtz++) { - if(mifare_nested_worker->state != MifareNestedWorkerStateCollecting) { - free(crypto); - return 1; - } - - nfc_activate(); - if(!furi_hal_nfc_activate_nfca(200, &cuid)) break; - - uint32_t delay = rtr * 1000 + rtz * 10; - - mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, false, &nt1); - - furi_delay_us(delay); - - mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, true, &nt2); - - // Searching for delay, where PRNG will be near 800 - uint32_t nttmp = prng_successor(nt1, 0); - - for(i = 1; i < 65565; i++) { - nttmp = prng_successor(nttmp, 1); - if(nttmp == nt2) break; - } - - if(!(i > previous - 50 && i < previous + 50) && rtz) { - repeat++; - - if(repeat < 5) { - FURI_LOG_D(TAG, "Invalid RPNG value: ntdist=%lu", i); - - continue; - } - } - - if(i > 2000 && i < 65500) { - uint32_t catch_cycles = (65565 - i) / prng_delay; - if(catch_cycles > 2) { - catch_cycles++; - - FURI_LOG_D( - TAG, - "Trying a more accurate value: skipping additional %lu us", - catch_cycles * 1000); - limit += catch_cycles + 2; - rtr += catch_cycles; - } - } - - FURI_LOG_D( - TAG, - "Calibrating: ntdist=%lu, delay=%lu, max=%lu", - i, - delay, - (cycles_to_reset + limit) * 1000); - - repeat = 0; - previous = i; - - if(i > 810 && i < 840) { - free(crypto); - FURI_LOG_I(TAG, "Found delay: %lu us", delay); - return delay; - } else if(i > 840 && i < 40000) { - FURI_LOG_D(TAG, "Trying again: timing lost"); - tries++; - free(crypto); - return mifare_nested_worker_predict_delay( - tx_rx, blockNo, keyType, ui64Key, tries, mifare_nested_worker); - } - } - } - - if(i > 1000 && i < 65000) { - FURI_LOG_D(TAG, "Trying again: wrong predicted timing"); - tries++; - free(crypto); - return mifare_nested_worker_predict_delay( - tx_rx, blockNo, keyType, ui64Key, tries, mifare_nested_worker); - } - - free(crypto); - - return 1; -} - -SaveNoncesResult_t* mifare_nested_worker_write_nonces( - FuriHalNfcDevData* data, - Storage* storage, - NonceList_t* nonces, - uint8_t tries_count, - uint8_t free_tries_count, - uint8_t sector_count, - uint32_t delay, - uint32_t distance) { - FuriString* path = furi_string_alloc(); - Stream* file_stream = file_stream_alloc(storage); - SaveNoncesResult_t* result = malloc(sizeof(SaveNoncesResult_t)); - result->saved = 0; - result->invalid = 0; - result->skipped = 0; - - mifare_nested_worker_get_nonces_file_path(data, path); - - file_stream_open(file_stream, furi_string_get_cstr(path), FSAM_READ_WRITE, FSOM_CREATE_ALWAYS); - - FuriString* header = furi_string_alloc_printf( - "Filetype: Flipper Nested Nonce Manifest File\nVersion: %s\nNote: you will need desktop app to recover keys: %s\n", - NESTED_NONCE_FORMAT_VERSION, - NESTED_RECOVER_KEYS_GITHUB_LINK); - stream_write_string(file_stream, header); - - for(uint8_t tries = 0; tries < tries_count; tries++) { - for(uint8_t sector = 0; sector < sector_count; sector++) { - for(uint8_t key_type = 0; key_type < 2; key_type++) { - if(nonces->nonces[sector][key_type][tries]->invalid) { - if(tries == 0) { - result->invalid++; - } - } else if(nonces->nonces[sector][key_type][tries]->skipped) { - if(tries == 0) { - result->skipped++; - } - } else if(nonces->nonces[sector][key_type][tries]->collected) { - if(nonces->nonces[sector][key_type][tries]->hardnested) { - FuriString* hardnested_path = furi_string_alloc(); - mifare_nested_worker_get_hardnested_file_path( - data, hardnested_path, sector, key_type); - - FuriString* str = furi_string_alloc_printf( - "HardNested: Key %c cuid 0x%08lx file %s sec %u\n", - !key_type ? 'A' : 'B', - nonces->cuid, - furi_string_get_cstr(hardnested_path), - sector); - - stream_write_string(file_stream, str); - - furi_string_free(hardnested_path); - furi_string_free(str); - } else { - FuriString* str = furi_string_alloc_printf( - "Nested: Key %c cuid 0x%08lx", !key_type ? 'A' : 'B', nonces->cuid); - - for(uint8_t type = 0; type < 2; type++) { - furi_string_cat_printf( - str, - " nt%u 0x%08lx ks%u 0x%08lx par%u ", - type, - nonces->nonces[sector][key_type][tries]->target_nt[type], - type, - nonces->nonces[sector][key_type][tries]->target_ks[type], - type); - - uint8_t* par = nonces->nonces[sector][key_type][tries]->parity[type]; - for(uint8_t i = 0; i < 4; i++) { - furi_string_cat_printf(str, "%u", par[i]); - } - } - - furi_string_cat_printf(str, " sec %u\n", sector); - - stream_write_string(file_stream, str); - furi_string_free(str); - } - - result->saved++; - } - } - } - } - - if(delay) { - FuriString* str = - furi_string_alloc_printf("Nested: Delay %lu, distance %lu", delay, distance); - - stream_write_string(file_stream, str); - furi_string_free(str); - } - - free_nonces(nonces, sector_count, free_tries_count); - file_stream_close(file_stream); - free(file_stream); - - if(!result->saved) { - FURI_LOG_E(TAG, "No nonces collected, removing file..."); - if(!storage_simply_remove(storage, furi_string_get_cstr(path))) { - FURI_LOG_E(TAG, "Failed to remove .nonces file"); - } - } - - furi_string_free(path); - furi_record_close(RECORD_STORAGE); - - return result; -} - -bool mifare_nested_worker_check_initial_keys( - NonceList_t* nonces, - MfClassicData* mf_data, - uint8_t tries_count, - uint8_t sector_count, - uint64_t* key, - uint32_t* key_block, - uint32_t* found_key_type) { - bool has_a_key, has_b_key; - FuriHalNfcTxRxContext tx_rx = {}; - - for(uint8_t sector = 0; sector < sector_count; sector++) { - for(uint8_t key_type = 0; key_type < 2; key_type++) { - for(uint8_t tries = 0; tries < tries_count; tries++) { - Nonces* info = malloc(sizeof(Nonces)); - info->key_type = key_type; - info->block = mifare_nested_worker_get_block_by_sector(sector); - info->collected = false; - info->skipped = true; - info->from_start = false; - - nonces->nonces[sector][key_type][tries] = info; - } - } - } - - for(uint8_t sector = 0; sector < sector_count; sector++) { - MfClassicSectorTrailer* trailer = - mifare_nested_worker_get_sector_trailer_by_sector(mf_data, sector); - has_a_key = FURI_BIT(mf_data->key_a_mask, sector); - has_b_key = FURI_BIT(mf_data->key_b_mask, sector); - - if(has_a_key) { - for(uint8_t tries = 0; tries < tries_count; tries++) { - Nonces* info = nonces->nonces[sector][0][tries]; - info->collected = true; - info->skipped = true; - info->from_start = true; - - nonces->nonces[sector][0][tries] = info; - } - - if(*key_block == 0) { - uint64_t key_check = nfc_util_bytes2num(trailer->key_a, 6); - if(nested_check_key( - &tx_rx, mifare_nested_worker_get_block_by_sector(sector), 0, key_check) == - NestedCheckKeyValid) { - *key = key_check; - *key_block = mifare_nested_worker_get_block_by_sector(sector); - *found_key_type = 0; - } - } - } - - if(has_b_key) { - for(uint8_t tries = 0; tries < tries_count; tries++) { - Nonces* info = nonces->nonces[sector][1][tries]; - info->collected = true; - info->skipped = true; - info->from_start = true; - - nonces->nonces[sector][1][tries] = info; - } - - if(*key_block == 0) { - uint64_t key_check = nfc_util_bytes2num(trailer->key_b, 6); - if(nested_check_key( - &tx_rx, mifare_nested_worker_get_block_by_sector(sector), 1, key_check) == - NestedCheckKeyValid) { - *key = key_check; - *key_block = mifare_nested_worker_get_block_by_sector(sector); - *found_key_type = 1; - } - } - } - } - - nonces->cuid = 0; - nonces->hardnested_states = 0; - nonces->sector_count = sector_count; - nonces->tries = tries_count; - - return *key_block; -} - -void mifare_nested_worker_check(MifareNestedWorker* mifare_nested_worker) { - while(mifare_nested_worker->state == MifareNestedWorkerStateCheck) { - FuriHalNfcTxRxContext tx_rx = {}; - NfcDevice* dev = mifare_nested_worker->context->nfc_dev; - MfClassicData* mf_data = &dev->dev_data.mf_classic_data; - FuriHalNfcDevData data = {}; - MifareNestedNonceType type = MifareNestedNonceNoTag; - nested_get_data(&data); - - if(mifare_nested_worker_read_key_cache(&data, mf_data)) { - for(uint8_t sector = 0; sector < 40; sector++) { - if(FURI_BIT(mf_data->key_a_mask, sector) || - FURI_BIT(mf_data->key_b_mask, sector)) { - type = nested_check_nonce_type( - &tx_rx, mifare_nested_worker_get_block_by_sector(sector)); - break; - } - } - - if(type == MifareNestedNonceNoTag) { - type = nested_check_nonce_type(&tx_rx, 0); - } - } else { - type = nested_check_nonce_type(&tx_rx, 0); - } - - if(type == MifareNestedNonceStatic) { - mifare_nested_worker->context->collecting_type = - MifareNestedWorkerStateCollectingStatic; - - mifare_nested_worker->callback( - MifareNestedWorkerEventCollecting, mifare_nested_worker->context); - - break; - } else if(type == MifareNestedNonceWeak) { - mifare_nested_worker->context->collecting_type = MifareNestedWorkerStateCollecting; - - mifare_nested_worker->callback( - MifareNestedWorkerEventCollecting, mifare_nested_worker->context); - - break; - } else if(type == MifareNestedNonceHard) { - mifare_nested_worker->context->collecting_type = MifareNestedWorkerStateCollectingHard; - - mifare_nested_worker->callback( - MifareNestedWorkerEventCollecting, mifare_nested_worker->context); - - break; - } - - furi_delay_ms(250); - } - - nfc_deactivate(); -} - -void mifare_nested_worker_collect_nonces_static(MifareNestedWorker* mifare_nested_worker) { - NonceList_t nonces; - Storage* storage = furi_record_open(RECORD_STORAGE); - NfcDevice* dev = mifare_nested_worker->context->nfc_dev; - MfClassicData* mf_data = &dev->dev_data.mf_classic_data; - FuriString* folder_path = furi_string_alloc(); - FuriHalNfcDevData data = {}; - nested_get_data(&data); - MfClassicType type = mifare_nested_worker_get_tag_type(data.atqa[0], data.atqa[1], data.sak); - uint64_t key = 0; // Found key for attack - uint32_t found_key_type = 0; - uint32_t key_block = 0; - uint32_t sector_count = 0; - - FURI_LOG_I(TAG, "Running Static Nested attack"); - FuriString* tag_info = furi_string_alloc_printf("Tag UID: "); - mifare_nested_worker_write_uid_string(&data, tag_info); - FURI_LOG_I(TAG, "%s", furi_string_get_cstr(tag_info)); - furi_string_free(tag_info); - - if(type == MfClassicType4k) { - sector_count = 40; - FURI_LOG_I(TAG, "Found Mifare Classic 4K tag"); - } else if(type == MfClassicType1k) { - sector_count = 16; - FURI_LOG_I(TAG, "Found Mifare Classic 1K tag"); - } else { // if(type == MfClassicTypeMini) - sector_count = 5; - FURI_LOG_I(TAG, "Found Mifare Classic Mini tag"); - } - - furi_string_set(folder_path, NESTED_FOLDER); - storage_common_mkdir(storage, furi_string_get_cstr(folder_path)); - furi_string_free(folder_path); - - if(!mifare_nested_worker_read_key_cache(&data, mf_data) || - !mifare_nested_worker_check_initial_keys( - &nonces, mf_data, 1, sector_count, &key, &key_block, &found_key_type)) { - mifare_nested_worker->callback( - MifareNestedWorkerEventNeedKey, mifare_nested_worker->context); - nfc_deactivate(); - - free(mf_data); - free_nonces(&nonces, sector_count, 1); - - return; - } - - FURI_LOG_I( - TAG, "Using %c key for block %lu: %012llX", !found_key_type ? 'A' : 'B', key_block, key); - - while(mifare_nested_worker->state == MifareNestedWorkerStateCollectingStatic) { - FuriHalNfcTxRxContext tx_rx = {}; - - for(uint8_t sector = 0; sector < sector_count; sector++) { - for(uint8_t key_type = 0; key_type < 2; key_type++) { - Nonces* info = nonces.nonces[sector][key_type][0]; - - if(info->collected) { - FURI_LOG_I( - TAG, - "Skipping sector %u, block %u, key_type: %u as we already have a key", - sector, - mifare_nested_worker_get_block_by_sector(sector), - key_type); - - info->skipped = true; - - nonces.nonces[sector][key_type][0] = info; - - mifare_nested_worker->context->nonces = &nonces; - - mifare_nested_worker->callback( - MifareNestedWorkerEventNewNonce, mifare_nested_worker->context); - continue; - } - - if(!nested_check_block( - &tx_rx, mifare_nested_worker_get_block_by_sector(sector), key_type)) { - FURI_LOG_E( - TAG, - "Skipping sector %u, block %u, key_type: %u as we can't auth on it", - sector, - mifare_nested_worker_get_block_by_sector(sector), - key_type); - - info->invalid = true; - - nonces.nonces[sector][key_type][0] = info; - - mifare_nested_worker->context->nonces = &nonces; - - mifare_nested_worker->callback( - MifareNestedWorkerEventNewNonce, mifare_nested_worker->context); - - continue; - } - - while(!info->collected) { - if(mifare_nested_worker->state != MifareNestedWorkerStateCollectingStatic) { - break; - } - - struct nonce_info_static result = nested_static_nonce_attack( - &tx_rx, - key_block, - found_key_type, - mifare_nested_worker_get_block_by_sector(sector), - key_type, - key); - if(result.full) { - FURI_LOG_I( - TAG, - "Accured nonces for sector %u, block %u, key_type: %u", - sector, - mifare_nested_worker_get_block_by_sector(sector), - key_type); - - info = nonces.nonces[sector][key_type][0]; - info->collected = true; - info->skipped = false; - - memcpy(&info->target_nt, result.target_nt, sizeof(result.target_nt)); - memcpy(&info->target_ks, result.target_ks, sizeof(result.target_ks)); - - nonces.nonces[sector][key_type][0] = info; - nonces.cuid = result.cuid; - nonces.sector_count = sector_count; - - mifare_nested_worker->context->nonces = &nonces; - - mifare_nested_worker->callback( - MifareNestedWorkerEventNewNonce, mifare_nested_worker->context); - break; - } else { - mifare_nested_worker->callback( - MifareNestedWorkerEventNoTagDetected, mifare_nested_worker->context); - } - } - } - } - - break; - } - - SaveNoncesResult_t* result = - mifare_nested_worker_write_nonces(&data, storage, &nonces, 1, 1, sector_count, 0, 0); - - free(mf_data); - - if(result->saved) { - mifare_nested_worker->callback( - MifareNestedWorkerEventNoncesCollected, mifare_nested_worker->context); - } else { - mifare_nested_worker->context->save_state = result; - - mifare_nested_worker->callback( - MifareNestedWorkerEventNoNoncesCollected, mifare_nested_worker->context); - } - - nfc_deactivate(); -} - -void mifare_nested_worker_collect_nonces_hard(MifareNestedWorker* mifare_nested_worker) { - NonceList_t nonces; - Storage* storage = furi_record_open(RECORD_STORAGE); - NfcDevice* dev = mifare_nested_worker->context->nfc_dev; - MfClassicData* mf_data = &dev->dev_data.mf_classic_data; - FuriString* folder_path = furi_string_alloc(); - FuriHalNfcDevData data = {}; - nested_get_data(&data); - MfClassicType type = mifare_nested_worker_get_tag_type(data.atqa[0], data.atqa[1], data.sak); - uint64_t key = 0; // Found key for attack - uint32_t found_key_type = 0; - uint32_t key_block = 0; - uint32_t sector_count = 0; - uint32_t cuid = 0; - furi_hal_nfc_activate_nfca(200, &cuid); - - FURI_LOG_I(TAG, "Running Hard Nested attack"); - FuriString* tag_info = furi_string_alloc_printf("Tag UID: "); - mifare_nested_worker_write_uid_string(&data, tag_info); - FURI_LOG_I(TAG, "%s", furi_string_get_cstr(tag_info)); - furi_string_free(tag_info); - - if(type == MfClassicType4k) { - sector_count = 40; - FURI_LOG_I(TAG, "Found Mifare Classic 4K tag"); - } else if(type == MfClassicType1k) { - sector_count = 16; - FURI_LOG_I(TAG, "Found Mifare Classic 1K tag"); - } else { // if(type == MfClassicTypeMini) - sector_count = 5; - FURI_LOG_I(TAG, "Found Mifare Classic Mini tag"); - } - - furi_string_set(folder_path, NESTED_FOLDER); - storage_common_mkdir(storage, furi_string_get_cstr(folder_path)); - mifare_nested_worker_get_hardnested_folder_path(&data, folder_path); - storage_common_mkdir(storage, furi_string_get_cstr(folder_path)); - furi_string_free(folder_path); - - if(!mifare_nested_worker_read_key_cache(&data, mf_data) || - !mifare_nested_worker_check_initial_keys( - &nonces, mf_data, 1, sector_count, &key, &key_block, &found_key_type)) { - mifare_nested_worker->callback( - MifareNestedWorkerEventNeedKey, mifare_nested_worker->context); - nfc_deactivate(); - - free(mf_data); - free_nonces(&nonces, sector_count, 1); - - return; - } - - FURI_LOG_I( - TAG, "Using %c key for block %lu: %012llX", !found_key_type ? 'A' : 'B', key_block, key); - - FuriHalNfcTxRxContext tx_rx = {}; - nonces.tries = 1; - nonces.hardnested_states = 0; - nonces.sector_count = sector_count; - - mifare_nested_worker->context->nonces = &nonces; - - mifare_nested_worker->callback(MifareNestedWorkerEventNewNonce, mifare_nested_worker->context); - - mifare_nested_worker->callback( - MifareNestedWorkerEventHardnestedStatesFound, mifare_nested_worker->context); - - for(uint8_t sector = 0; sector < sector_count && - mifare_nested_worker->state == MifareNestedWorkerStateCollectingHard; - sector++) { - for(uint8_t key_type = 0; - key_type < 2 && mifare_nested_worker->state == MifareNestedWorkerStateCollectingHard; - key_type++) { - Nonces* info = nonces.nonces[sector][key_type][0]; - if(info->collected) { - FURI_LOG_I( - TAG, - "Skipping sector %u, block %u, key_type: %u as we already have a key", - sector, - mifare_nested_worker_get_block_by_sector(sector), - key_type); - - info->skipped = true; - - nonces.nonces[sector][key_type][0] = info; - mifare_nested_worker->context->nonces = &nonces; - - mifare_nested_worker->callback( - MifareNestedWorkerEventNewNonce, mifare_nested_worker->context); - - continue; - } - - if(!nested_check_block( - &tx_rx, mifare_nested_worker_get_block_by_sector(sector), key_type)) { - FURI_LOG_E( - TAG, - "Skipping sector %u, block %u, key_type: %u as we can't auth on it", - sector, - mifare_nested_worker_get_block_by_sector(sector), - key_type); - - info->invalid = true; - - nonces.nonces[sector][key_type][0] = info; - mifare_nested_worker->context->nonces = &nonces; - - mifare_nested_worker->callback( - MifareNestedWorkerEventNewNonce, mifare_nested_worker->context); - - continue; - } - - while(!info->collected && - mifare_nested_worker->state == MifareNestedWorkerStateCollectingHard) { - Stream* file_stream = file_stream_alloc(storage); - FuriString* hardnested_file = furi_string_alloc(); - mifare_nested_worker_get_hardnested_file_path( - &data, hardnested_file, sector, key_type); - - file_stream_open( - file_stream, - furi_string_get_cstr(hardnested_file), - FSAM_READ_WRITE, - FSOM_CREATE_ALWAYS); - - FuriString* header = furi_string_alloc_printf( - "Filetype: Flipper Nested Nonces File\nVersion: %s\nNote: you will need desktop app to recover keys: %s\nKey %c cuid 0x%08lx sec %u\n", - NESTED_NONCE_FORMAT_VERSION, - NESTED_RECOVER_KEYS_GITHUB_LINK, - !key_type ? 'A' : 'B', - cuid, - sector); - - stream_write_string(file_stream, header); - furi_string_free(header); - - uint32_t first_byte_sum = 0; - uint32_t* found = malloc(sizeof(uint32_t) * 256); - for(uint32_t i = 0; i < 256; i++) { - found[i] = 0; - } - - while(mifare_nested_worker->state == MifareNestedWorkerStateCollectingHard) { - struct nonce_info_hard result = nested_hard_nonce_attack( - &tx_rx, - key_block, - found_key_type, - mifare_nested_worker_get_block_by_sector(sector), - key_type, - key, - found, - &first_byte_sum, - file_stream); - - if(result.static_encrypted) { - file_stream_close(file_stream); - - storage_simply_remove(storage, furi_string_get_cstr(hardnested_file)); - - furi_string_free(hardnested_file); - free(found); - free(mf_data); - nfc_deactivate(); - - mifare_nested_worker->callback( - MifareNestedWorkerEventStaticEncryptedNonce, - mifare_nested_worker->context); - - return; - } - - if(result.full) { - uint32_t states = 0; - for(uint32_t i = 0; i < 256; i++) { - states += found[i]; - } - - nonces.hardnested_states = states; - - mifare_nested_worker->callback( - MifareNestedWorkerEventHardnestedStatesFound, - mifare_nested_worker->context); - - FURI_LOG_D(TAG, "Found states: %lu", states); - - if(states == 256) { - FURI_LOG_D( - TAG, "All states collected, first_byte_sum: %lu", first_byte_sum); - - bool valid = false; - for(uint8_t i = 0; i < sizeof(sums); i++) { - if(sums[i] == first_byte_sum) { - valid = true; - break; - } - } - - if(!valid) { - FURI_LOG_E(TAG, "Invalid first_byte_sum!"); - break; - } - - info->collected = true; - info->hardnested = true; - info->skipped = false; - - nonces.cuid = result.cuid; - - nonces.nonces[sector][key_type][0] = info; - - mifare_nested_worker->context->nonces = &nonces; - - mifare_nested_worker->callback( - MifareNestedWorkerEventNewNonce, mifare_nested_worker->context); - - break; - } - } else { - mifare_nested_worker->callback( - MifareNestedWorkerEventNoTagDetected, mifare_nested_worker->context); - } - } - - free(found); - furi_string_free(hardnested_file); - file_stream_close(file_stream); - } - } - } - - SaveNoncesResult_t* result = - mifare_nested_worker_write_nonces(&data, storage, &nonces, 1, 1, sector_count, 0, 0); - - free(mf_data); - - if(result->saved) { - mifare_nested_worker->callback( - MifareNestedWorkerEventNoncesCollected, mifare_nested_worker->context); - } else { - mifare_nested_worker->context->save_state = result; - - mifare_nested_worker->callback( - MifareNestedWorkerEventNoNoncesCollected, mifare_nested_worker->context); - } - - nfc_deactivate(); -} - -void mifare_nested_worker_collect_nonces(MifareNestedWorker* mifare_nested_worker) { - NonceList_t nonces; - Storage* storage = furi_record_open(RECORD_STORAGE); - NfcDevice* dev = mifare_nested_worker->context->nfc_dev; - MfClassicData* mf_data = &dev->dev_data.mf_classic_data; - FuriString* folder_path = furi_string_alloc(); - FuriHalNfcDevData data = {}; - nested_get_data(&data); - MfClassicType type = mifare_nested_worker_get_tag_type(data.atqa[0], data.atqa[1], data.sak); - uint64_t key = 0; // Found key for attack - uint32_t found_key_type = 0; - uint32_t key_block = 0; - uint32_t sector_count = 0; - uint32_t delay = 0; - uint32_t distance = 0; - uint32_t tries_count = 1; - - FURI_LOG_I(TAG, "Running Nested attack"); - FuriString* tag_info = furi_string_alloc_printf("Tag UID: "); - mifare_nested_worker_write_uid_string(&data, tag_info); - FURI_LOG_I(TAG, "%s", furi_string_get_cstr(tag_info)); - furi_string_free(tag_info); - - if(type == MfClassicType4k) { - sector_count = 40; - FURI_LOG_I(TAG, "Found Mifare Classic 4K tag"); - } else if(type == MfClassicType1k) { - sector_count = 16; - FURI_LOG_I(TAG, "Found Mifare Classic 1K tag"); - } else { // if(type == MfClassicTypeMini) - sector_count = 5; - FURI_LOG_I(TAG, "Found Mifare Classic Mini tag"); - } - - furi_string_set(folder_path, NESTED_FOLDER); - storage_common_mkdir(storage, furi_string_get_cstr(folder_path)); - furi_string_free(folder_path); - - if(!mifare_nested_worker_read_key_cache(&data, mf_data) || - !mifare_nested_worker_check_initial_keys( - &nonces, mf_data, 3, sector_count, &key, &key_block, &found_key_type)) { - mifare_nested_worker->callback( - MifareNestedWorkerEventNeedKey, mifare_nested_worker->context); - nfc_deactivate(); - - free(mf_data); - free_nonces(&nonces, sector_count, 3); - - return; - } - - FURI_LOG_I( - TAG, "Using %c key for block %lu: %012llX", !found_key_type ? 'A' : 'B', key_block, key); - - while(mifare_nested_worker->state == MifareNestedWorkerStateCollecting) { - FuriHalNfcTxRxContext tx_rx = {}; - uint32_t first_distance = 0; - uint32_t second_distance = 0; - - mifare_nested_worker->callback( - MifareNestedWorkerEventCalibrating, mifare_nested_worker->context); - - distance = nested_calibrate_distance(&tx_rx, key_block, found_key_type, key, delay, false); - - if(mifare_nested_worker->state == MifareNestedWorkerStateCollecting) { - first_distance = - nested_calibrate_distance(&tx_rx, key_block, found_key_type, key, delay, true); - } - - if(mifare_nested_worker->state == MifareNestedWorkerStateCollecting) { - second_distance = - nested_calibrate_distance(&tx_rx, key_block, found_key_type, key, 10000, true); - } - - if(first_distance == 0 && second_distance == 0) { - nfc_deactivate(); - - free(mf_data); - free_nonces(&nonces, sector_count, 3); - - mifare_nested_worker_change_state( - mifare_nested_worker, MifareNestedWorkerStateCollectingHard); - - mifare_nested_worker_collect_nonces_hard(mifare_nested_worker); - return; - } - - if(first_distance < second_distance - 100 && second_distance > 100) { - FURI_LOG_E( - TAG, - "Discovered tag with PRNG that depends on time. PRNG values: %lu, %lu", - first_distance, - second_distance); - - struct distance_info info = - nested_calibrate_distance_info(&tx_rx, key_block, found_key_type, key); - - if(info.max_prng - info.min_prng > 150) { - FURI_LOG_W( - TAG, - "PRNG is too unpredictable (min/max values more than 150: %lu - %lu = %lu), fallback to delay method", - info.max_prng, - info.min_prng, - info.max_prng - info.min_prng); - - delay = 1; - } else { - FURI_LOG_I( - TAG, - "PRNG is stable, using method without delay! (May be false positive, still will collect x3 times)"); - - distance = - nested_calibrate_distance(&tx_rx, key_block, found_key_type, key, delay, true); - - delay = 2; - tries_count = 3; - } - } - - if(distance == 0 || delay == 1) { - bool failed = false; - // Tag need delay or unpredictable PRNG - FURI_LOG_W(TAG, "Can't determine distance, trying to find timing..."); - - mifare_nested_worker->callback( - MifareNestedWorkerEventNeedPrediction, mifare_nested_worker->context); - - delay = mifare_nested_worker_predict_delay( - &tx_rx, key_block, found_key_type, key, 0, mifare_nested_worker); - - if(delay == 1) { - FURI_LOG_E(TAG, "Can't determine delay"); - - // Check that we didn't lost tag - FuriHalNfcDevData lost_tag_data = {}; - nested_get_data(&lost_tag_data); - if(lost_tag_data.uid_len == 0) { - // We lost it. - mifare_nested_worker->callback( - MifareNestedWorkerEventNoTagDetected, mifare_nested_worker->context); - - while(mifare_nested_worker->state == MifareNestedWorkerStateCollecting && - lost_tag_data.cuid != data.cuid) { - furi_delay_ms(250); - nested_get_data(&lost_tag_data); - } - - mifare_nested_worker->callback( - MifareNestedWorkerEventCalibrating, mifare_nested_worker->context); - - continue; - } - - failed = true; - } - - if(delay == 2) { - FURI_LOG_E(TAG, "Can't determine delay in 25 tries, fallback to hardnested"); - - nfc_deactivate(); - - free(mf_data); - free_nonces(&nonces, sector_count, 3); - - mifare_nested_worker_change_state( - mifare_nested_worker, MifareNestedWorkerStateCollectingHard); - - mifare_nested_worker_collect_nonces_hard(mifare_nested_worker); - return; - } - - if(mifare_nested_worker->state == MifareNestedWorkerStateCollecting && !failed) { - distance = nested_calibrate_distance( - &tx_rx, key_block, found_key_type, key, delay, false); - } - - if(distance == 0 && !failed) { - FURI_LOG_E(TAG, "Found delay, but can't find distance"); - - failed = true; - } - - if(failed) { - nfc_deactivate(); - - mifare_nested_worker->callback( - MifareNestedWorkerEventAttackFailed, mifare_nested_worker->context); - - free(mf_data); - free_nonces(&nonces, sector_count, 3); - - return; - } - - tries_count = 3; - } - - mifare_nested_worker->context->nonces = &nonces; - - mifare_nested_worker->callback( - MifareNestedWorkerEventNewNonce, mifare_nested_worker->context); - - for(uint8_t tries = 0; tries < tries_count; tries++) { - for(uint8_t sector = 0; sector < sector_count; sector++) { - for(uint8_t key_type = 0; key_type < 2; key_type++) { - Nonces* info = nonces.nonces[sector][key_type][tries]; - if(info->collected) { - FURI_LOG_I( - TAG, - "Skipping sector %u, block %u, key_type: %u as we already have a key", - sector, - mifare_nested_worker_get_block_by_sector(sector), - key_type); - - info->skipped = true; - - nonces.nonces[sector][key_type][tries] = info; - mifare_nested_worker->context->nonces = &nonces; - - mifare_nested_worker->callback( - MifareNestedWorkerEventNewNonce, mifare_nested_worker->context); - - continue; - } - - if(!nested_check_block( - &tx_rx, mifare_nested_worker_get_block_by_sector(sector), key_type)) { - FURI_LOG_E( - TAG, - "Skipping sector %u, block %u, key_type: %u as we can't auth on it", - sector, - mifare_nested_worker_get_block_by_sector(sector), - key_type); - - info->skipped = true; - - nonces.nonces[sector][key_type][0] = info; - mifare_nested_worker->context->nonces = &nonces; - - mifare_nested_worker->callback( - MifareNestedWorkerEventNewNonce, mifare_nested_worker->context); - - continue; - } - - while(!info->collected) { - if(mifare_nested_worker->state != MifareNestedWorkerStateCollecting) { - break; - } - - struct nonce_info result = nested_attack( - &tx_rx, - key_block, - found_key_type, - mifare_nested_worker_get_block_by_sector(sector), - key_type, - key, - distance, - delay); - - if(result.full) { - FURI_LOG_I( - TAG, - "Accured nonces for sector %u, block %u, key_type: %u", - sector, - mifare_nested_worker_get_block_by_sector(sector), - key_type); - - info = nonces.nonces[sector][key_type][tries]; - info->collected = true; - info->skipped = false; - - memcpy(&info->target_nt, result.target_nt, sizeof(result.target_nt)); - memcpy(&info->target_ks, result.target_ks, sizeof(result.target_ks)); - memcpy(&info->parity, result.parity, sizeof(result.parity)); - - nonces.nonces[sector][key_type][tries] = info; - nonces.cuid = result.cuid; - nonces.sector_count = sector_count; - nonces.tries = tries_count; - - mifare_nested_worker->context->nonces = &nonces; - - mifare_nested_worker->callback( - MifareNestedWorkerEventNewNonce, mifare_nested_worker->context); - break; - } else { - mifare_nested_worker->callback( - MifareNestedWorkerEventNoTagDetected, - mifare_nested_worker->context); - } - } - } - } - } - - break; - } - - SaveNoncesResult_t* result = mifare_nested_worker_write_nonces( - &data, storage, &nonces, tries_count, 3, sector_count, delay, distance); - - free(mf_data); - - if(result->saved) { - mifare_nested_worker->callback( - MifareNestedWorkerEventNoncesCollected, mifare_nested_worker->context); - } else { - mifare_nested_worker->context->save_state = result; - - mifare_nested_worker->callback( - MifareNestedWorkerEventNoNoncesCollected, mifare_nested_worker->context); - } - - nfc_deactivate(); -} - -bool* mifare_nested_worker_check_keys_exists( - Storage* storage, - char* path, - uint64_t* keys, - uint32_t key_count, - MifareNestedWorker* mifare_nested_worker) { - bool* old_keys = malloc(sizeof(bool) * key_count); - Stream* file_stream = file_stream_alloc(storage); - file_stream_open(file_stream, path, FSAM_READ, FSOM_OPEN_ALWAYS); - FuriString* key_strings[key_count]; - - for(uint32_t i = 0; i < key_count; i++) { - old_keys[i] = false; - key_strings[i] = furi_string_alloc_printf("%012llX\n", keys[i]); - } - - while(mifare_nested_worker->state == MifareNestedWorkerStateValidating) { - FuriString* next_line = furi_string_alloc(); - - if(!stream_read_line(file_stream, next_line)) { - break; - } - - for(uint32_t i = 0; i < key_count; i++) { - if(keys[i] == (uint64_t)-1) continue; - - if(furi_string_cmp(next_line, key_strings[i]) == 0) { - old_keys[i] = true; - } - } - - furi_string_free(next_line); - } - - for(uint32_t i = 0; i < key_count; i++) { - furi_string_free(key_strings[i]); - } - - file_stream_close(file_stream); - free(file_stream); - - return old_keys; -} - -void mifare_nested_worker_write_key(Storage* storage, FuriString* key) { - Stream* file_stream = file_stream_alloc(storage); - file_stream_open( - file_stream, - EXT_PATH("nfc/assets/mf_classic_dict_user.nfc"), - FSAM_READ_WRITE, - FSOM_OPEN_APPEND); - - stream_write_string(file_stream, key); - - file_stream_close(file_stream); -} - -void mifare_nested_worker_check_keys(MifareNestedWorker* mifare_nested_worker) { - KeyInfo_t* key_info = mifare_nested_worker->context->keys; - Storage* storage = furi_record_open(RECORD_STORAGE); - Stream* file_stream = file_stream_alloc(storage); - FuriString* next_line = furi_string_alloc(); - FuriString* path = furi_string_alloc(); - FuriHalNfcDevData data = {}; - nested_get_data(&data); - MfClassicType type = mifare_nested_worker_get_tag_type(data.atqa[0], data.atqa[1], data.sak); - NestedCheckKeyResult result = NestedCheckKeyNoTag; - FuriHalNfcTxRxContext tx_rx = {}; - uint32_t key_count = 0; - uint32_t sector_key_count = 0; - uint64_t keys[80]; - bool found_keys[2][40]; - bool unique_keys[2][40]; - uint32_t sector_count = 0; - - if(type == MfClassicType4k) { - sector_count = 40; - FURI_LOG_I(TAG, "Found Mifare Classic 4K tag"); - } else if(type == MfClassicType1k) { - sector_count = 16; - FURI_LOG_I(TAG, "Found Mifare Classic 1K tag"); - } else { // if(type == MfClassicTypeMini) - sector_count = 5; - FURI_LOG_I(TAG, "Found Mifare Classic Mini tag"); - } - - uint32_t keys_count = sector_count * 2; - - for(uint8_t key = 0; key < 2; key++) { - for(uint8_t i = 0; i < sector_count; i++) { - found_keys[key][i] = false; - unique_keys[key][i] = false; - } - } - - for(uint8_t i = 0; i < keys_count; i++) { - keys[i] = -1; - } - - mifare_nested_worker_get_found_keys_file_path(&data, path); - - if(!file_stream_open(file_stream, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { - FURI_LOG_E(TAG, "Can't open %s", furi_string_get_cstr(path)); - - file_stream_close(file_stream); - - mifare_nested_worker_get_nonces_file_path(&data, path); - - if(!file_stream_open( - file_stream, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { - mifare_nested_worker->callback( - MifareNestedWorkerEventNeedCollection, mifare_nested_worker->context); - } else { - mifare_nested_worker->callback( - MifareNestedWorkerEventNeedKeyRecovery, mifare_nested_worker->context); - } - - file_stream_close(file_stream); - - free(file_stream); - furi_string_free(path); - furi_string_free(next_line); - furi_record_close(RECORD_STORAGE); - - return; - }; - - while(true) { - if(!stream_read_line(file_stream, next_line)) { - break; - } - - if(furi_string_start_with_str(next_line, "Key")) { - uint8_t key_type = furi_string_get_char(next_line, 4) == 'B'; - uint8_t sector = atoi((char[]){furi_string_get_char(next_line, 13)}) * 10 + - atoi((char[]){furi_string_get_char(next_line, 14)}); - - if(!unique_keys[key_type][sector]) { - unique_keys[key_type][sector] = true; - sector_key_count++; - } - } - - key_count++; - } - - stream_rewind(file_stream); - - key_info->total_keys = key_count; - key_info->sector_keys = sector_key_count; - - while(mifare_nested_worker->state == MifareNestedWorkerStateValidating) { - if(!stream_read_line(file_stream, next_line)) { - break; - } - - if(furi_string_start_with_str(next_line, "Key")) { - // Key X sector XX: XX XX XX XX XX XX - // 0000000000111111111122222222223333 - // 0123456789012345678901234567890123 - uint8_t keyChar[6]; - uint8_t count = 0; - - uint8_t key_type = furi_string_get_char(next_line, 4) == 'B'; - uint8_t sector = atoi((char[]){furi_string_get_char(next_line, 13)}) * 10 + - atoi((char[]){furi_string_get_char(next_line, 14)}); - - for(uint8_t i = 17; i < 33; i += 3) { - hex_char_to_uint8( - furi_string_get_char(next_line, i), - furi_string_get_char(next_line, i + 1), - &keyChar[count]); - count++; - } - - uint64_t key = nfc_util_bytes2num(keyChar, 6); - - key_info->checked_keys++; - - if(found_keys[key_type][sector]) { - mifare_nested_worker->callback( - MifareNestedWorkerEventKeyChecked, mifare_nested_worker->context); - - continue; - } - - while(mifare_nested_worker->state == MifareNestedWorkerStateValidating) { - result = nested_check_key( - &tx_rx, mifare_nested_worker_get_block_by_sector(sector), key_type, key); - - if(result == NestedCheckKeyNoTag) { - mifare_nested_worker->callback( - MifareNestedWorkerEventNoTagDetected, mifare_nested_worker->context); - - furi_delay_ms(250); - } else { - break; - } - } - - if(result == NestedCheckKeyValid) { - FURI_LOG_I( - TAG, "Found valid %c key for sector %u: %012llX", key_type, sector, key); - bool exists = false; - - for(uint8_t i = 0; i < keys_count; i++) { - if(keys[i] == key) { - exists = true; - } - } - - if(!exists) { - keys[key_info->found_keys] = key; - } - - key_info->found_keys++; - found_keys[key_type][sector] = true; - } - - mifare_nested_worker->callback( - MifareNestedWorkerEventKeyChecked, mifare_nested_worker->context); - } - } - - furi_string_free(next_line); - file_stream_close(file_stream); - free(file_stream); - - mifare_nested_worker->callback( - MifareNestedWorkerEventProcessingKeys, mifare_nested_worker->context); - - bool* old_keys = mifare_nested_worker_check_keys_exists( - storage, - EXT_PATH("nfc/assets/mf_classic_dict_user.nfc"), - keys, - keys_count, - mifare_nested_worker); - - for(uint8_t i = 0; i < keys_count; i++) { - if(old_keys[i]) { - keys[i] = -1; - } - } - - old_keys = mifare_nested_worker_check_keys_exists( - storage, - EXT_PATH("nfc/assets/mf_classic_dict.nfc"), - keys, - keys_count, - mifare_nested_worker); - - for(uint8_t i = 0; i < keys_count; i++) { - if(old_keys[i]) { - keys[i] = -1; - } - } - - for(uint8_t i = 0; i < keys_count; i++) { - if(keys[i] == (uint64_t)-1) continue; - - FuriString* key_string = furi_string_alloc_printf("%012llX\n", keys[i]); - - mifare_nested_worker_write_key(storage, key_string); - FURI_LOG_I(TAG, "Added new key: %s", furi_string_get_cstr(key_string)); - - key_info->added_keys++; - - furi_string_free(key_string); - } - - if(!storage_simply_remove(storage, furi_string_get_cstr(path))) { - FURI_LOG_E(TAG, "Failed to remove .keys file"); - } - - furi_record_close(RECORD_STORAGE); - furi_string_free(path); - - mifare_nested_worker->callback( - MifareNestedWorkerEventKeysFound, mifare_nested_worker->context); - - return; -} \ No newline at end of file diff --git a/applications/external/mifare_nested/mifare_nested_worker.h b/applications/external/mifare_nested/mifare_nested_worker.h deleted file mode 100644 index 99c691749..000000000 --- a/applications/external/mifare_nested/mifare_nested_worker.h +++ /dev/null @@ -1,98 +0,0 @@ -#pragma once - -#include - -#define NESTED_FOLDER EXT_PATH("nfc/.nested") - -typedef struct MifareNestedWorker MifareNestedWorker; - -typedef enum { - MifareNestedWorkerStateReady, - - MifareNestedWorkerStateCheck, - MifareNestedWorkerStateCollecting, - MifareNestedWorkerStateCollectingStatic, - MifareNestedWorkerStateCollectingHard, - MifareNestedWorkerStateValidating, - - MifareNestedWorkerStateStop, -} MifareNestedWorkerState; - -typedef enum { - MifareNestedWorkerEventReserved = 1000, - - MifareNestedWorkerEventNoTagDetected, - MifareNestedWorkerEventNoNoncesCollected, - MifareNestedWorkerEventNoncesCollected, - MifareNestedWorkerEventCollecting, - - MifareNestedWorkerEventNewNonce, - MifareNestedWorkerEventKeyChecked, - MifareNestedWorkerEventKeysFound, - MifareNestedWorkerEventNeedKey, - MifareNestedWorkerEventAttackFailed, - MifareNestedWorkerEventCalibrating, - MifareNestedWorkerEventStaticEncryptedNonce, - MifareNestedWorkerEventNeedPrediction, - MifareNestedWorkerEventProcessingKeys, - MifareNestedWorkerEventNeedKeyRecovery, - MifareNestedWorkerEventNeedCollection, - MifareNestedWorkerEventHardnestedStatesFound -} MifareNestedWorkerEvent; - -typedef bool (*MifareNestedWorkerCallback)(MifareNestedWorkerEvent event, void* context); - -MifareNestedWorker* mifare_nested_worker_alloc(); - -void mifare_nested_worker_change_state( - MifareNestedWorker* mifare_nested_worker, - MifareNestedWorkerState state); - -void mifare_nested_worker_free(MifareNestedWorker* mifare_nested_worker); - -void mifare_nested_worker_stop(MifareNestedWorker* mifare_nested_worker); - -void mifare_nested_worker_start( - MifareNestedWorker* mifare_nested_worker, - MifareNestedWorkerState state, - NfcDeviceData* dev_data, - MifareNestedWorkerCallback callback, - void* context); - -typedef struct { - uint32_t key_type; - uint32_t block; - uint32_t target_nt[2]; - uint32_t target_ks[2]; - uint8_t parity[2][4]; - bool skipped; - bool from_start; - bool invalid; - bool collected; - bool hardnested; -} Nonces; - -typedef struct { - uint32_t cuid; - uint32_t sector_count; - // 40 (or 16/5) sectors, 2 keys (A/B), 3 tries - Nonces* nonces[40][2][3]; - uint32_t tries; - // unique first bytes - uint32_t hardnested_states; -} NonceList_t; - -typedef struct { - uint32_t total_keys; - uint32_t checked_keys; - uint32_t found_keys; - uint32_t added_keys; - uint32_t sector_keys; - bool tag_lost; -} KeyInfo_t; - -typedef struct { - uint32_t saved; - uint32_t invalid; - uint32_t skipped; -} SaveNoncesResult_t; \ No newline at end of file diff --git a/applications/external/mifare_nested/mifare_nested_worker_i.h b/applications/external/mifare_nested/mifare_nested_worker_i.h deleted file mode 100644 index fd82535d0..000000000 --- a/applications/external/mifare_nested/mifare_nested_worker_i.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include -#include "mifare_nested_i.h" -#include "mifare_nested_worker.h" - -struct MifareNestedWorker { - FuriThread* thread; - - NfcDeviceData* dev_data; - - MifareNestedWorkerCallback callback; - MifareNested* context; - - MifareNestedWorkerState state; -}; - -int32_t mifare_nested_worker_task(void* context); - -void mifare_nested_worker_check(MifareNestedWorker* mifare_nested_worker); - -void mifare_nested_worker_collect_nonces(MifareNestedWorker* mifare_nested_worker); - -void mifare_nested_worker_collect_nonces_static(MifareNestedWorker* mifare_nested_worker); - -void mifare_nested_worker_collect_nonces_hard(MifareNestedWorker* mifare_nested_worker); - -void mifare_nested_worker_check_keys(MifareNestedWorker* mifare_nested_worker); diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene.c b/applications/external/mifare_nested/scenes/mifare_nested_scene.c deleted file mode 100644 index 3962ed908..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "mifare_nested_scene.h" - -// Generate scene on_enter handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, -void (*const mifare_nested_on_enter_handlers[])(void*) = { -#include "mifare_nested_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_event handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, -bool (*const mifare_nested_on_event_handlers[])(void* context, SceneManagerEvent event) = { -#include "mifare_nested_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_exit handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, -void (*const mifare_nested_on_exit_handlers[])(void* context) = { -#include "mifare_nested_scene_config.h" -}; -#undef ADD_SCENE - -// Initialize scene handlers configuration structure -const SceneManagerHandlers mifare_nested_scene_handlers = { - .on_enter_handlers = mifare_nested_on_enter_handlers, - .on_event_handlers = mifare_nested_on_event_handlers, - .on_exit_handlers = mifare_nested_on_exit_handlers, - .scene_num = MifareNestedSceneNum, -}; diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene.h b/applications/external/mifare_nested/scenes/mifare_nested_scene.h deleted file mode 100644 index e9596f222..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -// Generate scene id and total number -#define ADD_SCENE(prefix, name, id) MifareNestedScene##id, -typedef enum { -#include "mifare_nested_scene_config.h" - MifareNestedSceneNum, -} MifareNestedScene; -#undef ADD_SCENE - -extern const SceneManagerHandlers mifare_nested_scene_handlers; - -// Generate scene on_enter handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); -#include "mifare_nested_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_event handlers declaration -#define ADD_SCENE(prefix, name, id) \ - bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); -#include "mifare_nested_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_exit handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); -#include "mifare_nested_scene_config.h" -#undef ADD_SCENE diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_about.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_about.c deleted file mode 100644 index 9aa46f698..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_about.c +++ /dev/null @@ -1,77 +0,0 @@ -#include "../mifare_nested_i.h" - -void mifare_nested_scene_about_widget_callback(GuiButtonType result, InputType type, void* context) { - MifareNested* mifare_nested = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, result); - } -} - -void mifare_nested_scene_about_on_enter(void* context) { - MifareNested* mifare_nested = context; - - FuriString* temp_str; - temp_str = furi_string_alloc(); - furi_string_printf(temp_str, "\e#%s\n", "Information"); - - furi_string_cat_printf(temp_str, "Version: %s\n", NESTED_VERSION_APP); - furi_string_cat_printf(temp_str, "Developed by:\n%s\n\n", NESTED_AUTHOR); - furi_string_cat_printf(temp_str, "Github: %s\n\n", NESTED_GITHUB_LINK); - - furi_string_cat_printf(temp_str, "\e#%s\n", "Description"); - furi_string_cat_printf( - temp_str, - "Ported Nested attacks\nfrom Proxmark3 (Iceman fork)\nCurrently supported attacks:\n - nested attack\n - static nested attack\n - hard nested attack\n\n"); - furi_string_cat_printf( - temp_str, - "You will need desktop app to recover keys from collected nonces: %s\n\n", - NESTED_RECOVER_KEYS_GITHUB_LINK); - furi_string_cat_printf(temp_str, "\e#%s\n", "Quick guide"); - furi_string_cat_printf(temp_str, "1. Install key recovery script on PC:\n"); - furi_string_cat_printf(temp_str, "pip install FlipperNested\n"); - furi_string_cat_printf(temp_str, "2. Connect Flipper Zero to PC\n"); - furi_string_cat_printf(temp_str, "3. Run key recovery:\n"); - furi_string_cat_printf(temp_str, "FlipperNested"); - - widget_add_text_box_element( - mifare_nested->widget, - 0, - 0, - 128, - 14, - AlignCenter, - AlignBottom, - "\e#\e! \e!\n", - false); - widget_add_text_box_element( - mifare_nested->widget, - 0, - 2, - 128, - 14, - AlignCenter, - AlignBottom, - "\e#\e! Flipper Nested \e!\n", - false); - widget_add_text_scroll_element( - mifare_nested->widget, 0, 16, 128, 50, furi_string_get_cstr(temp_str)); - furi_string_free(temp_str); - - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewWidget); -} - -bool mifare_nested_scene_about_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - bool consumed = false; - UNUSED(mifare_nested); - UNUSED(event); - - return consumed; -} - -void mifare_nested_scene_about_on_exit(void* context) { - MifareNested* mifare_nested = context; - - // Clear views - widget_reset(mifare_nested->widget); -} diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_added_keys.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_added_keys.c deleted file mode 100644 index f5627a300..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_added_keys.c +++ /dev/null @@ -1,76 +0,0 @@ -#include "../mifare_nested_i.h" - -void mifare_nested_scene_added_keys_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - MifareNested* mifare_nested = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, result); - } -} - -void mifare_nested_scene_added_keys_on_enter(void* context) { - MifareNested* mifare_nested = context; - KeyInfo_t* key_info = mifare_nested->keys; - Widget* widget = mifare_nested->widget; - char draw_str[32] = {}; - char append[5] = {'k', 'e', 'y', ' ', '\0'}; - if(key_info->added_keys != 1) { - append[3] = 's'; - } - - widget_add_string_element( - widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Results of key recovery"); - - if(key_info->added_keys != 0) { - snprintf(draw_str, sizeof(draw_str), "Added: %lu %s", key_info->added_keys, append); - notification_message(mifare_nested->notifications, &sequence_success); - widget_add_icon_element(widget, 52, 17, &I_DolphinSuccess); - } else { - snprintf(draw_str, sizeof(draw_str), "No new keys were added"); - widget_add_string_element( - widget, 0, 22, AlignLeft, AlignTop, FontSecondary, "Try running \"Nested attack\""); - widget_add_string_element(widget, 0, 32, AlignLeft, AlignTop, FontSecondary, "again"); - notification_message(mifare_nested->notifications, &sequence_error); - } - - widget_add_string_element(widget, 0, 12, AlignLeft, AlignTop, FontSecondary, draw_str); - widget_add_button_element( - widget, - GuiButtonTypeLeft, - "Back", - mifare_nested_scene_added_keys_widget_callback, - mifare_nested); - - free(key_info); - - KeyInfo_t* new_key_info = malloc(sizeof(KeyInfo_t)); - mifare_nested->keys = new_key_info; - - // Setup and start worker - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewWidget); -} - -bool mifare_nested_scene_added_keys_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeCenter || event.event == GuiButtonTypeLeft) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeBack) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - - return consumed; -} - -void mifare_nested_scene_added_keys_on_exit(void* context) { - MifareNested* mifare_nested = context; - - widget_reset(mifare_nested->widget); -} diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_check.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_check.c deleted file mode 100644 index 45837ff92..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_check.c +++ /dev/null @@ -1,95 +0,0 @@ -#include "../mifare_nested_i.h" - -enum { - MifareNestedSceneCheckStateTagSearch, - MifareNestedSceneCheckStateTagFound, -}; - -bool mifare_nested_check_worker_callback(MifareNestedWorkerEvent event, void* context) { - furi_assert(context); - - MifareNested* mifare_nested = context; - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, event); - - return true; -} - -static void mifare_nested_scene_check_setup_view(MifareNested* mifare_nested) { - Popup* popup = mifare_nested->popup; - popup_reset(popup); - uint32_t state = - scene_manager_get_scene_state(mifare_nested->scene_manager, MifareNestedSceneCheck); - - if(state == MifareNestedSceneCheckStateTagSearch) { - popup_set_icon(mifare_nested->popup, 0, 8, &I_ApplyTag); - popup_set_text( - mifare_nested->popup, "Apply tag to\nthe back", 128, 32, AlignRight, AlignCenter); - } else { - popup_set_icon(popup, 12, 23, &I_Loading); - popup_set_header(popup, "Checking\nDon't move...", 52, 32, AlignLeft, AlignCenter); - } - - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewPopup); -} - -void mifare_nested_scene_check_on_enter(void* context) { - MifareNested* mifare_nested = context; - - scene_manager_set_scene_state( - mifare_nested->scene_manager, - MifareNestedSceneCheck, - MifareNestedSceneCheckStateTagSearch); - mifare_nested_scene_check_setup_view(mifare_nested); - - // Setup and start worker - mifare_nested_worker_start( - mifare_nested->worker, - MifareNestedWorkerStateCheck, - &mifare_nested->nfc_dev->dev_data, - mifare_nested_check_worker_callback, - mifare_nested); - mifare_nested_blink_start(mifare_nested); -} - -bool mifare_nested_scene_check_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == MifareNestedWorkerEventCollecting) { - if(mifare_nested->run == NestedRunAttack) { - if(mifare_nested->settings->only_hardnested) { - FURI_LOG_I("MifareNested", "Using Hard Nested because user settings"); - mifare_nested->collecting_type = MifareNestedWorkerStateCollectingHard; - } - scene_manager_next_scene( - mifare_nested->scene_manager, MifareNestedSceneCollecting); - } else { - scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneCheckKeys); - } - consumed = true; - } else if(event.event == MifareNestedWorkerEventNoTagDetected) { - scene_manager_set_scene_state( - mifare_nested->scene_manager, - MifareNestedSceneCheck, - MifareNestedSceneCheckStateTagSearch); - mifare_nested_scene_check_setup_view(mifare_nested); - consumed = true; - } - } - return consumed; -} - -void mifare_nested_scene_check_on_exit(void* context) { - MifareNested* mifare_nested = context; - - mifare_nested_worker_stop(mifare_nested->worker); - scene_manager_set_scene_state( - mifare_nested->scene_manager, - MifareNestedSceneCheck, - MifareNestedSceneCheckStateTagSearch); - // Clear view - popup_reset(mifare_nested->popup); - - mifare_nested_blink_stop(mifare_nested); -} diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_check_keys.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_check_keys.c deleted file mode 100644 index b06953eeb..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_check_keys.c +++ /dev/null @@ -1,117 +0,0 @@ -#include "../mifare_nested_i.h" - -void mifare_nested_scene_check_keys_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - MifareNested* mifare_nested = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, result); - } -} - -bool mifare_nested_check_keys_worker_callback(MifareNestedWorkerEvent event, void* context) { - MifareNested* mifare_nested = context; - CheckKeysState* plugin_state = mifare_nested->keys_state; - - if(event == MifareNestedWorkerEventKeyChecked) { - mifare_nested_blink_nonce_collection_start(mifare_nested); - - KeyInfo_t* key_info = mifare_nested->keys; - - with_view_model( - plugin_state->view, - CheckKeysViewModel * model, - { - model->lost_tag = false; - model->keys_checked = key_info->checked_keys; - model->keys_found = key_info->found_keys; - model->keys_total = key_info->sector_keys; - model->keys_count = key_info->total_keys; - }, - true); - } else if(event == MifareNestedWorkerEventNoTagDetected) { - mifare_nested_blink_start(mifare_nested); - - with_view_model( - plugin_state->view, CheckKeysViewModel * model, { model->lost_tag = true; }, true); - } else if(event == MifareNestedWorkerEventProcessingKeys) { - with_view_model( - plugin_state->view, - CheckKeysViewModel * model, - { model->processing_keys = true; }, - true); - } - - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, event); - - return true; -} - -void mifare_nested_scene_check_keys_on_enter(void* context) { - MifareNested* mifare_nested = context; - CheckKeysState* plugin_state = mifare_nested->keys_state; - - mifare_nested_worker_start( - mifare_nested->worker, - MifareNestedWorkerStateValidating, - &mifare_nested->nfc_dev->dev_data, - mifare_nested_check_keys_worker_callback, - mifare_nested); - - mifare_nested_blink_start(mifare_nested); - - with_view_model( - plugin_state->view, - CheckKeysViewModel * model, - { - model->lost_tag = false; - model->processing_keys = false; - model->keys_count = 0; - model->keys_checked = 0; - model->keys_found = 0; - }, - false); - - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewCheckKeys); -} - -bool mifare_nested_scene_check_keys_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - - bool consumed = false; - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeCenter) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } else if(event.event == MifareNestedWorkerEventKeysFound) { - scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneAddedKeys); - consumed = true; - } else if(event.event == MifareNestedWorkerEventNeedKeyRecovery) { - scene_manager_next_scene( - mifare_nested->scene_manager, MifareNestedSceneNeedKeyRecovery); - consumed = true; - } else if(event.event == MifareNestedWorkerEventNeedCollection) { - scene_manager_next_scene( - mifare_nested->scene_manager, MifareNestedSceneNeedCollection); - consumed = true; - } else if( - event.event == MifareNestedWorkerEventKeyChecked || - event.event == MifareNestedWorkerEventNoTagDetected || - event.event == MifareNestedWorkerEventProcessingKeys) { - consumed = true; - } - } - - return consumed; -} - -void mifare_nested_scene_check_keys_on_exit(void* context) { - MifareNested* mifare_nested = context; - mifare_nested_worker_stop(mifare_nested->worker); - - // Clear view - mifare_nested_blink_stop(mifare_nested); - popup_reset(mifare_nested->popup); - widget_reset(mifare_nested->widget); -} diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_collecting.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_collecting.c deleted file mode 100644 index 0e319bbcf..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_collecting.c +++ /dev/null @@ -1,161 +0,0 @@ -#include "../mifare_nested_i.h" - -void mifare_nested_scene_collecting_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - MifareNested* mifare_nested = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, result); - } -} - -bool mifare_nested_collecting_worker_callback(MifareNestedWorkerEvent event, void* context) { - MifareNested* mifare_nested = context; - NestedState* plugin_state = mifare_nested->nested_state; - - if(event == MifareNestedWorkerEventNewNonce) { - mifare_nested_blink_nonce_collection_start(mifare_nested); - - uint8_t collected = 0; - uint8_t skip = 0; - NonceList_t* nonces = mifare_nested->nonces; - for(uint8_t tries = 0; tries < nonces->tries; tries++) { - for(uint8_t sector = 0; sector < nonces->sector_count; sector++) { - for(uint8_t keyType = 0; keyType < 2; keyType++) { - Nonces* info = nonces->nonces[sector][keyType][tries]; - if(info->from_start) { - skip++; - } else if(info->collected) { - collected++; - } - } - } - } - - with_view_model( - plugin_state->view, - NestedAttackViewModel * model, - { - model->calibrating = false; - model->lost_tag = false; - model->nonces_collected = collected; - model->keys_count = (nonces->sector_count * nonces->tries * 2) - skip; - }, - true); - } else if(event == MifareNestedWorkerEventNoTagDetected) { - mifare_nested_blink_start(mifare_nested); - - with_view_model( - plugin_state->view, NestedAttackViewModel * model, { model->lost_tag = true; }, true); - } else if(event == MifareNestedWorkerEventCalibrating) { - mifare_nested_blink_calibration_start(mifare_nested); - - with_view_model( - plugin_state->view, - NestedAttackViewModel * model, - { - model->calibrating = true; - model->lost_tag = false; - model->need_prediction = false; - model->hardnested = false; - }, - true); - } else if(event == MifareNestedWorkerEventNeedPrediction) { - with_view_model( - plugin_state->view, - NestedAttackViewModel * model, - { model->need_prediction = true; }, - true); - } else if(event == MifareNestedWorkerEventHardnestedStatesFound) { - NonceList_t* nonces = mifare_nested->nonces; - with_view_model( - plugin_state->view, - NestedAttackViewModel * model, - { - model->calibrating = false; - model->lost_tag = false; - model->hardnested = true; - model->hardnested_states = nonces->hardnested_states; - }, - true); - } - - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, event); - - return true; -} - -void mifare_nested_scene_collecting_on_enter(void* context) { - MifareNested* mifare_nested = context; - NestedState* nested = mifare_nested->nested_state; - - mifare_nested_worker_start( - mifare_nested->worker, - mifare_nested->collecting_type, - &mifare_nested->nfc_dev->dev_data, - mifare_nested_collecting_worker_callback, - mifare_nested); - - mifare_nested_blink_start(mifare_nested); - - with_view_model( - nested->view, - NestedAttackViewModel * model, - { - model->lost_tag = false; - model->nonces_collected = 0; - }, - false); - - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewCollecting); -} - -bool mifare_nested_scene_collecting_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - - bool consumed = false; - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeCenter) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } else if(event.event == MifareNestedWorkerEventNoncesCollected) { - scene_manager_next_scene( - mifare_nested->scene_manager, MifareNestedSceneNoncesCollected); - consumed = true; - } else if(event.event == MifareNestedWorkerEventNoNoncesCollected) { - scene_manager_next_scene( - mifare_nested->scene_manager, MifareNestedSceneNoNoncesCollected); - consumed = true; - } else if(event.event == MifareNestedWorkerEventAttackFailed) { - scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneFailed); - consumed = true; - } else if(event.event == MifareNestedWorkerEventNeedKey) { - scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneNoKeys); - consumed = true; - } else if(event.event == MifareNestedWorkerEventStaticEncryptedNonce) { - scene_manager_next_scene( - mifare_nested->scene_manager, MifareNestedSceneStaticEncryptedNonce); - consumed = true; - } else if( - event.event == MifareNestedWorkerEventNewNonce || - event.event == MifareNestedWorkerEventNoTagDetected || - event.event == MifareNestedWorkerEventCalibrating || - event.event == MifareNestedWorkerEventNeedPrediction || - event.event == MifareNestedWorkerEventHardnestedStatesFound) { - consumed = true; - } - } - - return consumed; -} - -void mifare_nested_scene_collecting_on_exit(void* context) { - MifareNested* mifare_nested = context; - mifare_nested_worker_stop(mifare_nested->worker); - - // Clear view - mifare_nested_blink_stop(mifare_nested); - popup_reset(mifare_nested->popup); - widget_reset(mifare_nested->widget); -} \ No newline at end of file diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_config.h b/applications/external/mifare_nested/scenes/mifare_nested_scene_config.h deleted file mode 100644 index 648f0bd73..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_config.h +++ /dev/null @@ -1,14 +0,0 @@ -ADD_SCENE(mifare_nested, start, Start) -ADD_SCENE(mifare_nested, check, Check) -ADD_SCENE(mifare_nested, nonces_collected, NoncesCollected) -ADD_SCENE(mifare_nested, collecting, Collecting) -ADD_SCENE(mifare_nested, no_keys, NoKeys) -ADD_SCENE(mifare_nested, check_keys, CheckKeys) -ADD_SCENE(mifare_nested, added_keys, AddedKeys) -ADD_SCENE(mifare_nested, failed, Failed) -ADD_SCENE(mifare_nested, about, About) -ADD_SCENE(mifare_nested, static_encrypted_nonce, StaticEncryptedNonce) -ADD_SCENE(mifare_nested, need_key_recovery, NeedKeyRecovery) -ADD_SCENE(mifare_nested, need_collection, NeedCollection) -ADD_SCENE(mifare_nested, settings, Settings) -ADD_SCENE(mifare_nested, no_nonces_collected, NoNoncesCollected) \ No newline at end of file diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_failed.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_failed.c deleted file mode 100644 index e7d1ee80d..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_failed.c +++ /dev/null @@ -1,59 +0,0 @@ -#include "../mifare_nested_i.h" - -void mifare_nested_scene_failed_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - MifareNested* mifare_nested = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, result); - } -} - -void mifare_nested_scene_failed_on_enter(void* context) { - MifareNested* mifare_nested = context; - Widget* widget = mifare_nested->widget; - - notification_message(mifare_nested->notifications, &sequence_error); - - widget_add_icon_element(widget, 73, 13, &I_DolphinCry); - widget_add_string_element( - widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Failed to preform attack"); - widget_add_string_element(widget, 0, 12, AlignLeft, AlignTop, FontSecondary, "Try running"); - widget_add_string_element( - widget, 0, 22, AlignLeft, AlignTop, FontSecondary, "\"Nested attack\""); - widget_add_string_element(widget, 0, 32, AlignLeft, AlignTop, FontSecondary, "again or check"); - widget_add_string_element(widget, 0, 42, AlignLeft, AlignTop, FontSecondary, "logs"); - widget_add_button_element( - widget, - GuiButtonTypeLeft, - "Back", - mifare_nested_scene_failed_widget_callback, - mifare_nested); - - // Setup and start worker - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewWidget); -} - -bool mifare_nested_scene_failed_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeCenter || event.event == GuiButtonTypeLeft) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeBack) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - - return consumed; -} - -void mifare_nested_scene_failed_on_exit(void* context) { - MifareNested* mifare_nested = context; - - widget_reset(mifare_nested->widget); -} diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_need_collection.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_need_collection.c deleted file mode 100644 index ee6e76b40..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_need_collection.c +++ /dev/null @@ -1,56 +0,0 @@ -#include "../mifare_nested_i.h" - -void mifare_nested_scene_need_collection_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - MifareNested* mifare_nested = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, result); - } -} - -void mifare_nested_scene_need_collection_on_enter(void* context) { - MifareNested* mifare_nested = context; - Widget* widget = mifare_nested->widget; - - notification_message(mifare_nested->notifications, &sequence_error); - - widget_add_icon_element(widget, 73, 13, &I_DolphinCry); - widget_add_string_element( - widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Missing collected nonces"); - widget_add_string_element( - widget, 0, 12, AlignLeft, AlignTop, FontSecondary, "Run \"Nested attack\""); - widget_add_button_element( - widget, - GuiButtonTypeLeft, - "Back", - mifare_nested_scene_need_collection_widget_callback, - mifare_nested); - - // Setup and start worker - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewWidget); -} - -bool mifare_nested_scene_need_collection_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeCenter || event.event == GuiButtonTypeLeft) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeBack) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - - return consumed; -} - -void mifare_nested_scene_need_collection_on_exit(void* context) { - MifareNested* mifare_nested = context; - - widget_reset(mifare_nested->widget); -} diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_need_key_recovery.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_need_key_recovery.c deleted file mode 100644 index e34b68137..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_need_key_recovery.c +++ /dev/null @@ -1,59 +0,0 @@ -#include "../mifare_nested_i.h" - -void mifare_nested_scene_need_key_recovery_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - MifareNested* mifare_nested = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, result); - } -} - -void mifare_nested_scene_need_key_recovery_on_enter(void* context) { - MifareNested* mifare_nested = context; - Widget* widget = mifare_nested->widget; - - notification_message(mifare_nested->notifications, &sequence_error); - - widget_add_icon_element(widget, 74, 13, &I_DolphinCry); - widget_add_string_element( - widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Missing found keys"); - widget_add_string_element( - widget, 0, 12, AlignLeft, AlignTop, FontSecondary, "First you need to"); - widget_add_string_element(widget, 0, 22, AlignLeft, AlignTop, FontSecondary, "recover keys"); - widget_add_string_element(widget, 0, 32, AlignLeft, AlignTop, FontSecondary, "Read \"About\""); - widget_add_string_element(widget, 0, 42, AlignLeft, AlignTop, FontSecondary, "for more info"); - widget_add_button_element( - widget, - GuiButtonTypeLeft, - "Back", - mifare_nested_scene_need_key_recovery_widget_callback, - mifare_nested); - - // Setup and start worker - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewWidget); -} - -bool mifare_nested_scene_need_key_recovery_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeCenter || event.event == GuiButtonTypeLeft) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeBack) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - - return consumed; -} - -void mifare_nested_scene_need_key_recovery_on_exit(void* context) { - MifareNested* mifare_nested = context; - - widget_reset(mifare_nested->widget); -} diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_no_keys.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_no_keys.c deleted file mode 100644 index 138cbdbc8..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_no_keys.c +++ /dev/null @@ -1,61 +0,0 @@ -#include "../mifare_nested_i.h" - -void mifare_nested_scene_no_keys_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - MifareNested* mifare_nested = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, result); - } -} - -void mifare_nested_scene_no_keys_on_enter(void* context) { - MifareNested* mifare_nested = context; - Widget* widget = mifare_nested->widget; - - notification_message(mifare_nested->notifications, &sequence_success); - - widget_add_icon_element(widget, 73, 13, &I_DolphinCry); - widget_add_string_element(widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "No keys found"); - widget_add_string_element( - widget, 0, 12, AlignLeft, AlignTop, FontSecondary, "Scan tag and find at"); - widget_add_string_element( - widget, 0, 22, AlignLeft, AlignTop, FontSecondary, "least one key to"); - widget_add_string_element( - widget, 0, 32, AlignLeft, AlignTop, FontSecondary, "start (save dump"); - widget_add_string_element( - widget, 0, 42, AlignLeft, AlignTop, FontSecondary, "after scanning!)"); - widget_add_button_element( - widget, - GuiButtonTypeLeft, - "Back", - mifare_nested_scene_no_keys_widget_callback, - mifare_nested); - - // Setup and start worker - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewWidget); -} - -bool mifare_nested_scene_no_keys_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeCenter || event.event == GuiButtonTypeLeft) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeBack) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - - return consumed; -} - -void mifare_nested_scene_no_keys_on_exit(void* context) { - MifareNested* mifare_nested = context; - - widget_reset(mifare_nested->widget); -} diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_no_nonces_collected.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_no_nonces_collected.c deleted file mode 100644 index 74e2459e8..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_no_nonces_collected.c +++ /dev/null @@ -1,94 +0,0 @@ -#include "../mifare_nested_i.h" - -void mifare_nested_scene_no_nonces_collected_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - MifareNested* mifare_nested = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, result); - } -} - -void mifare_nested_scene_no_nonces_collected_on_enter(void* context) { - MifareNested* mifare_nested = context; - Widget* widget = mifare_nested->widget; - SaveNoncesResult_t* save_state = mifare_nested->save_state; - - notification_message(mifare_nested->notifications, &sequence_error); - - widget_add_icon_element(widget, 73, 12, &I_DolphinCry); - widget_add_string_element( - widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "No nonces collected"); - - uint32_t index = 12; - - if(save_state->skipped) { - char append_skipped[8] = {'s', 'e', 'c', 't', 'o', 'r', ' ', '\0'}; - if(save_state->skipped != 1) { - append_skipped[6] = 's'; - } - - char draw_str[32] = {}; - snprintf( - draw_str, sizeof(draw_str), "Skipped: %lu %s", save_state->skipped, append_skipped); - - widget_add_string_element(widget, 0, index, AlignLeft, AlignTop, FontSecondary, draw_str); - - widget_add_string_element( - widget, 0, index + 10, AlignLeft, AlignTop, FontSecondary, "(already has keys)"); - - index += 20; - } - - if(save_state->invalid) { - char append_invalid[8] = {'s', 'e', 'c', 't', 'o', 'r', ' ', '\0'}; - if(save_state->invalid != 1) { - append_invalid[6] = 's'; - } - - char draw_str[32] = {}; - snprintf( - draw_str, sizeof(draw_str), "Invalid: %lu %s", save_state->invalid, append_invalid); - - widget_add_string_element(widget, 0, index, AlignLeft, AlignTop, FontSecondary, draw_str); - - widget_add_string_element( - widget, 0, index + 10, AlignLeft, AlignTop, FontSecondary, "(can't auth)"); - } - - free(save_state); - - widget_add_button_element( - widget, - GuiButtonTypeLeft, - "Back", - mifare_nested_scene_no_nonces_collected_widget_callback, - mifare_nested); - - // Setup and start worker - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewWidget); -} - -bool mifare_nested_scene_no_nonces_collected_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeCenter || event.event == GuiButtonTypeLeft) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeBack) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - - return consumed; -} - -void mifare_nested_scene_no_nonces_collected_on_exit(void* context) { - MifareNested* mifare_nested = context; - - widget_reset(mifare_nested->widget); -} diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_nonces_collected.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_nonces_collected.c deleted file mode 100644 index cc543645f..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_nonces_collected.c +++ /dev/null @@ -1,58 +0,0 @@ -#include "../mifare_nested_i.h" - -void mifare_nested_scene_nonces_collected_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - MifareNested* mifare_nested = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, result); - } -} - -void mifare_nested_scene_nonces_collected_on_enter(void* context) { - MifareNested* mifare_nested = context; - Widget* widget = mifare_nested->widget; - - notification_message(mifare_nested->notifications, &sequence_success); - - widget_add_icon_element(widget, 52, 17, &I_DolphinSuccess); - widget_add_string_element(widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Nonces collected"); - widget_add_string_element( - widget, 0, 12, AlignLeft, AlignTop, FontSecondary, "Now you can run"); - widget_add_string_element(widget, 0, 22, AlignLeft, AlignTop, FontSecondary, "script on your"); - widget_add_string_element(widget, 0, 32, AlignLeft, AlignTop, FontSecondary, "PC to recover"); - widget_add_string_element(widget, 0, 42, AlignLeft, AlignTop, FontSecondary, "keys"); - widget_add_button_element( - widget, - GuiButtonTypeLeft, - "Back", - mifare_nested_scene_nonces_collected_widget_callback, - mifare_nested); - - // Setup and start worker - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewWidget); -} - -bool mifare_nested_scene_nonces_collected_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeCenter || event.event == GuiButtonTypeLeft) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeBack) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - - return consumed; -} - -void mifare_nested_scene_nonces_collected_on_exit(void* context) { - MifareNested* mifare_nested = context; - - widget_reset(mifare_nested->widget); -} diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_settings.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_settings.c deleted file mode 100644 index 09d77f94b..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_settings.c +++ /dev/null @@ -1,65 +0,0 @@ -#include "../mifare_nested_i.h" -#include - -enum MifareNestedSettingsIndex { MifareNestedIndexBlock, MifareNestedIndexHardNested }; - -#define HARD_NESTED_COUNT 2 -const char* const hard_nested_text[HARD_NESTED_COUNT] = { - "No", - "Yes", -}; - -const bool hard_nested_value[HARD_NESTED_COUNT] = { - false, - true, -}; - -static void mifare_nested_scene_settings_set_hard_nested(VariableItem* item) { - MifareNested* mifare_nested = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - - variable_item_set_current_value_text(item, hard_nested_text[index]); - mifare_nested->settings->only_hardnested = hard_nested_value[index]; -} - -void mifare_nested_scene_settings_on_enter(void* context) { - MifareNested* mifare_nested = context; - VariableItem* item; - uint8_t value_index; - - item = variable_item_list_add( - mifare_nested->variable_item_list, - "Hard Nested only:", - HARD_NESTED_COUNT, - mifare_nested_scene_settings_set_hard_nested, - mifare_nested); - - value_index = value_index_bool( - mifare_nested->settings->only_hardnested, hard_nested_value, HARD_NESTED_COUNT); - - variable_item_set_current_value_index(item, value_index); - variable_item_set_current_value_text(item, hard_nested_text[value_index]); - - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewVariableList); -} - -bool mifare_nested_scene_settings_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == MifareNestedCustomEventSceneSettingLock) { - scene_manager_previous_scene(mifare_nested->scene_manager); - consumed = true; - } - } - - return consumed; -} - -void mifare_nested_scene_settings_on_exit(void* context) { - MifareNested* mifare_nested = context; - variable_item_list_set_selected_item(mifare_nested->variable_item_list, 0); - variable_item_list_reset(mifare_nested->variable_item_list); - scene_manager_set_scene_state(mifare_nested->scene_manager, MifareNestedSceneStart, 0); -} diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_start.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_start.c deleted file mode 100644 index e8ff25c67..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_start.c +++ /dev/null @@ -1,84 +0,0 @@ -#include "../mifare_nested_i.h" -enum SubmenuIndex { - SubmenuIndexCollect, - SubmenuIndexCheck, - SubmenuIndexSettings, - SubmenuIndexAbout -}; - -void mifare_nested_scene_start_submenu_callback(void* context, uint32_t index) { - MifareNested* mifare_nested = context; - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, index); -} - -void mifare_nested_scene_start_on_enter(void* context) { - MifareNested* mifare_nested = context; - - Submenu* submenu = mifare_nested->submenu; - submenu_add_item( - submenu, - "Nested attack", - SubmenuIndexCollect, - mifare_nested_scene_start_submenu_callback, - mifare_nested); - - submenu_add_item( - submenu, - "Check found keys", - SubmenuIndexCheck, - mifare_nested_scene_start_submenu_callback, - mifare_nested); - - submenu_add_item( - submenu, - "Settings", - SubmenuIndexSettings, - mifare_nested_scene_start_submenu_callback, - mifare_nested); - - submenu_add_item( - submenu, - "About", - SubmenuIndexAbout, - mifare_nested_scene_start_submenu_callback, - mifare_nested); - - submenu_set_selected_item( - submenu, - scene_manager_get_scene_state(mifare_nested->scene_manager, MifareNestedSceneStart)); - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewMenu); -} - -bool mifare_nested_scene_start_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexCollect) { - mifare_nested->run = NestedRunAttack; - scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneCheck); - consumed = true; - } else if(event.event == SubmenuIndexCheck) { - mifare_nested->run = NestedRunCheckKeys; - scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneCheck); - consumed = true; - } else if(event.event == SubmenuIndexSettings) { - mifare_nested->keys->found_keys = 123; - scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneSettings); - consumed = true; - } else if(event.event == SubmenuIndexAbout) { - scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneAbout); - consumed = true; - } - - scene_manager_set_scene_state( - mifare_nested->scene_manager, MifareNestedSceneStart, event.event); - } - - return consumed; -} - -void mifare_nested_scene_start_on_exit(void* context) { - MifareNested* mifare_nested = context; - submenu_reset(mifare_nested->submenu); -} diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_static_encrypted_nonce.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_static_encrypted_nonce.c deleted file mode 100644 index 92cefa72c..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_static_encrypted_nonce.c +++ /dev/null @@ -1,58 +0,0 @@ -#include "../mifare_nested_i.h" - -void mifare_nested_scene_static_encrypted_nonce_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - MifareNested* mifare_nested = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, result); - } -} - -void mifare_nested_scene_static_encrypted_nonce_on_enter(void* context) { - MifareNested* mifare_nested = context; - Widget* widget = mifare_nested->widget; - - notification_message(mifare_nested->notifications, &sequence_error); - - widget_add_icon_element(widget, 73, 12, &I_DolphinCry); - widget_add_string_element( - widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Static encrypted nonce"); - widget_add_string_element(widget, 0, 12, AlignLeft, AlignTop, FontSecondary, "This tag isn't"); - widget_add_string_element(widget, 0, 22, AlignLeft, AlignTop, FontSecondary, "vulnerable to"); - widget_add_string_element(widget, 0, 32, AlignLeft, AlignTop, FontSecondary, "Nested attack"); - - widget_add_button_element( - widget, - GuiButtonTypeLeft, - "Back", - mifare_nested_scene_static_encrypted_nonce_widget_callback, - mifare_nested); - - // Setup and start worker - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewWidget); -} - -bool mifare_nested_scene_static_encrypted_nonce_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeCenter || event.event == GuiButtonTypeLeft) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeBack) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - - return consumed; -} - -void mifare_nested_scene_static_encrypted_nonce_on_exit(void* context) { - MifareNested* mifare_nested = context; - - widget_reset(mifare_nested->widget); -} diff --git a/applications/external/music_tracker/application.fam b/applications/external/music_tracker/application.fam deleted file mode 100644 index 5aba35cd3..000000000 --- a/applications/external/music_tracker/application.fam +++ /dev/null @@ -1,16 +0,0 @@ -App( - appid="zero_tracker", - name="Zero Tracker", - apptype=FlipperAppType.EXTERNAL, - entry_point="zero_tracker_app", - requires=[ - "gui", - ], - stack_size=4 * 1024, - fap_icon="zero_tracker.png", - fap_category="Media", - fap_author="@DrZlo13", - fap_weburl="https://github.com/DrZlo13/flipper-zero-music-tracker", - fap_version="1.1", - fap_description="App plays hardcoded tracker song", -) diff --git a/applications/external/music_tracker/tracker_engine/speaker_hal.c b/applications/external/music_tracker/tracker_engine/speaker_hal.c deleted file mode 100644 index 112439b1e..000000000 --- a/applications/external/music_tracker/tracker_engine/speaker_hal.c +++ /dev/null @@ -1,109 +0,0 @@ -#include "speaker_hal.h" - -#define FURI_HAL_SPEAKER_TIMER TIM16 -#define FURI_HAL_SPEAKER_CHANNEL LL_TIM_CHANNEL_CH1 -#define FURI_HAL_SPEAKER_PRESCALER 500 - -void tracker_speaker_play(float frequency, float pwm) { - uint32_t autoreload = (SystemCoreClock / FURI_HAL_SPEAKER_PRESCALER / frequency) - 1; - if(autoreload < 2) { - autoreload = 2; - } else if(autoreload > UINT16_MAX) { - autoreload = UINT16_MAX; - } - - if(pwm < 0) pwm = 0; - if(pwm > 1) pwm = 1; - - uint32_t compare_value = pwm * autoreload; - - if(compare_value == 0) { - compare_value = 1; - } - - if(LL_TIM_OC_GetCompareCH1(FURI_HAL_SPEAKER_TIMER) != compare_value) { - LL_TIM_OC_SetCompareCH1(FURI_HAL_SPEAKER_TIMER, compare_value); - } - - if(LL_TIM_GetAutoReload(FURI_HAL_SPEAKER_TIMER) != autoreload) { - LL_TIM_SetAutoReload(FURI_HAL_SPEAKER_TIMER, autoreload); - if(LL_TIM_GetCounter(FURI_HAL_SPEAKER_TIMER) > autoreload) { - LL_TIM_SetCounter(FURI_HAL_SPEAKER_TIMER, 0); - } - } - - LL_TIM_EnableAllOutputs(FURI_HAL_SPEAKER_TIMER); -} - -void tracker_speaker_stop() { - LL_TIM_DisableAllOutputs(FURI_HAL_SPEAKER_TIMER); -} - -void tracker_speaker_init() { - if(furi_hal_speaker_is_mine() || furi_hal_speaker_acquire(1000)) { - furi_hal_speaker_start(200.0f, 0.01f); - tracker_speaker_stop(); - } -} - -void tracker_speaker_deinit() { - if(furi_hal_speaker_is_mine()) { - furi_hal_speaker_stop(); - furi_hal_speaker_release(); - } -} - -static FuriHalInterruptISR tracker_isr; -static void* tracker_isr_context; -static void tracker_interrupt_cb(void* context) { - UNUSED(context); - - if(LL_TIM_IsActiveFlag_UPDATE(TIM2)) { - LL_TIM_ClearFlag_UPDATE(TIM2); - - if(tracker_isr) { - tracker_isr(tracker_isr_context); - } - } -} - -void tracker_interrupt_init(float freq, FuriHalInterruptISR isr, void* context) { - tracker_isr = isr; - tracker_isr_context = context; - - furi_hal_bus_enable(FuriHalBusTIM2); - - furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, tracker_interrupt_cb, NULL); - - LL_TIM_InitTypeDef TIM_InitStruct = {0}; - // Prescaler to get 1kHz clock - TIM_InitStruct.Prescaler = SystemCoreClock / 1000000 - 1; - TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; - // Auto reload to get freq Hz interrupt - TIM_InitStruct.Autoreload = (1000000 / freq) - 1; - TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1; - LL_TIM_Init(TIM2, &TIM_InitStruct); - LL_TIM_EnableIT_UPDATE(TIM2); - LL_TIM_EnableAllOutputs(TIM2); - LL_TIM_EnableCounter(TIM2); -} - -void tracker_interrupt_deinit() { - FURI_CRITICAL_ENTER(); - furi_hal_bus_disable(FuriHalBusTIM2); - FURI_CRITICAL_EXIT(); - - furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, NULL, NULL); -} - -void tracker_debug_init() { - furi_hal_gpio_init(&gpio_ext_pc3, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); -} - -void tracker_debug_set(bool value) { - furi_hal_gpio_write(&gpio_ext_pc3, value); -} - -void tracker_debug_deinit() { - furi_hal_gpio_init(&gpio_ext_pc3, GpioModeAnalog, GpioPullNo, GpioSpeedLow); -} \ No newline at end of file diff --git a/applications/external/music_tracker/tracker_engine/speaker_hal.h b/applications/external/music_tracker/tracker_engine/speaker_hal.h deleted file mode 100644 index 7867fe93f..000000000 --- a/applications/external/music_tracker/tracker_engine/speaker_hal.h +++ /dev/null @@ -1,19 +0,0 @@ -#include - -void tracker_speaker_init(); - -void tracker_speaker_deinit(); - -void tracker_speaker_play(float frequency, float pwm); - -void tracker_speaker_stop(); - -void tracker_interrupt_init(float freq, FuriHalInterruptISR isr, void* context); - -void tracker_interrupt_deinit(); - -void tracker_debug_init(); - -void tracker_debug_set(bool value); - -void tracker_debug_deinit(); \ No newline at end of file diff --git a/applications/external/music_tracker/tracker_engine/tracker.c b/applications/external/music_tracker/tracker_engine/tracker.c deleted file mode 100644 index e5efcea17..000000000 --- a/applications/external/music_tracker/tracker_engine/tracker.c +++ /dev/null @@ -1,441 +0,0 @@ -#include "tracker.h" -#include -#include "speaker_hal.h" - -// SongState song_state = { -// .tick = 0, -// .tick_limit = 2, -// .row = 0, -// }; - -typedef struct { - uint8_t speed; - uint8_t depth; - int8_t direction; - int8_t value; -} IntegerOscillator; - -typedef struct { - float frequency; - float frequency_target; - float pwm; - bool play; - IntegerOscillator vibrato; -} ChannelState; - -typedef struct { - ChannelState* channels; - uint8_t tick; - uint8_t tick_limit; - - uint8_t pattern_index; - uint8_t row_index; - uint8_t order_list_index; -} SongState; - -typedef struct { - uint8_t note; - uint8_t effect; - uint8_t data; -} UnpackedRow; - -struct Tracker { - const Song* song; - bool playing; - TrackerMessageCallback callback; - void* context; - SongState song_state; -}; - -static void channels_state_init(ChannelState* channel) { - channel->frequency = 0; - channel->frequency_target = FREQUENCY_UNSET; - channel->pwm = PWM_DEFAULT; - channel->play = false; - channel->vibrato.speed = 0; - channel->vibrato.depth = 0; - channel->vibrato.direction = 0; - channel->vibrato.value = 0; -} - -static void tracker_song_state_init(Tracker* tracker) { - tracker->song_state.tick = 0; - tracker->song_state.tick_limit = 2; - tracker->song_state.row_index = 0; - tracker->song_state.order_list_index = 0; - tracker->song_state.pattern_index = tracker->song->order_list[0]; - - if(tracker->song_state.channels != NULL) { - free(tracker->song_state.channels); - } - - tracker->song_state.channels = malloc(sizeof(ChannelState) * tracker->song->channels_count); - for(uint8_t i = 0; i < tracker->song->channels_count; i++) { - channels_state_init(&tracker->song_state.channels[i]); - } -} - -static void tracker_song_state_clear(Tracker* tracker) { - if(tracker->song_state.channels != NULL) { - free(tracker->song_state.channels); - tracker->song_state.channels = NULL; - } -} - -static uint8_t record_get_note(Row note) { - return note & ROW_NOTE_MASK; -} - -static uint8_t record_get_effect(Row note) { - return (note >> 6) & ROW_EFFECT_MASK; -} - -static uint8_t record_get_effect_data(Row note) { - return (note >> 10) & ROW_EFFECT_DATA_MASK; -} - -#define NOTES_PER_OCT 12 -const float notes_oct[NOTES_PER_OCT] = { - 130.813f, - 138.591f, - 146.832f, - 155.563f, - 164.814f, - 174.614f, - 184.997f, - 195.998f, - 207.652f, - 220.00f, - 233.082f, - 246.942f, -}; - -static float note_to_freq(uint8_t note) { - if(note == NOTE_NONE) return 0.0f; - note = note - NOTE_C2; - uint8_t octave = note / NOTES_PER_OCT; - uint8_t note_in_oct = note % NOTES_PER_OCT; - return notes_oct[note_in_oct] * (1 << octave); -} - -static float frequency_offset_semitones(float frequency, uint8_t semitones) { - return frequency * (1.0f + ((1.0f / 12.0f) * semitones)); -} - -static float frequency_get_seventh_of_a_semitone(float frequency) { - return frequency * ((1.0f / 12.0f) / 7.0f); -} - -static UnpackedRow get_current_row(const Song* song, SongState* song_state, uint8_t channel) { - const Pattern* pattern = &song->patterns[song_state->pattern_index]; - const Row row = pattern->channels[channel].rows[song_state->row_index]; - return (UnpackedRow){ - .note = record_get_note(row), - .effect = record_get_effect(row), - .data = record_get_effect_data(row), - }; -} - -static int16_t advance_order_and_get_next_pattern_index(const Song* song, SongState* song_state) { - song_state->order_list_index++; - if(song_state->order_list_index >= song->order_list_size) { - return -1; - } else { - return song->order_list[song_state->order_list_index]; - } -} - -typedef struct { - int16_t pattern; - int16_t row; - bool change_pattern; - bool change_row; -} Location; - -static void tracker_send_position_message(Tracker* tracker) { - if(tracker->callback != NULL) { - tracker->callback( - (TrackerMessage){ - .type = TrackerPositionChanged, - .data = - { - .position = - { - .order_list_index = tracker->song_state.order_list_index, - .row = tracker->song_state.row_index, - }, - }, - }, - tracker->context); - } -} - -static void tracker_send_end_message(Tracker* tracker) { - if(tracker->callback != NULL) { - tracker->callback((TrackerMessage){.type = TrackerEndOfSong}, tracker->context); - } -} - -static void advance_to_pattern(Tracker* tracker, Location advance) { - if(advance.change_pattern) { - if(advance.pattern < 0 || advance.pattern >= tracker->song->patterns_count) { - tracker->playing = false; - tracker_send_end_message(tracker); - } else { - tracker->song_state.pattern_index = advance.pattern; - tracker->song_state.row_index = 0; - } - } - - if(advance.change_row) { - if(advance.row < 0) advance.row = 0; - if(advance.row >= PATTERN_SIZE) advance.row = PATTERN_SIZE - 1; - tracker->song_state.row_index = advance.row; - } - - tracker_send_position_message(tracker); -} - -static void tracker_interrupt_body(Tracker* tracker) { - if(!tracker->playing) { - tracker_speaker_stop(); - return; - } - - const uint8_t channel_index = 0; - SongState* song_state = &tracker->song_state; - ChannelState* channel_state = &song_state->channels[channel_index]; - const Song* song = tracker->song; - UnpackedRow row = get_current_row(song, song_state, channel_index); - - // load frequency from note at tick 0 - if(song_state->tick == 0) { - bool invalidate_row = false; - // handle "on first tick" effects - if(row.effect == EffectBreakPattern) { - int16_t next_row_index = row.data; - int16_t next_pattern_index = - advance_order_and_get_next_pattern_index(song, song_state); - advance_to_pattern( - tracker, - (Location){ - .pattern = next_pattern_index, - .row = next_row_index, - .change_pattern = true, - .change_row = true, - }); - - invalidate_row = true; - } - - if(row.effect == EffectJumpToOrder) { - song_state->order_list_index = row.data; - int16_t next_pattern_index = song->order_list[song_state->order_list_index]; - - advance_to_pattern( - tracker, - (Location){ - .pattern = next_pattern_index, - .change_pattern = true, - }); - - invalidate_row = true; - } - - // tracker state can be affected by effects - if(!tracker->playing) { - tracker_speaker_stop(); - return; - } - - if(invalidate_row) { - row = get_current_row(song, song_state, channel_index); - - if(row.effect == EffectSetSpeed) { - song_state->tick_limit = row.data; - } - } - - // handle note effects - if(row.note == NOTE_OFF) { - channel_state->play = false; - } else if((row.note > NOTE_NONE) && (row.note < NOTE_OFF)) { - channel_state->play = true; - - // reset vibrato - channel_state->vibrato.speed = 0; - channel_state->vibrato.depth = 0; - channel_state->vibrato.value = 0; - channel_state->vibrato.direction = 0; - - // reset pwm - channel_state->pwm = PWM_DEFAULT; - - if(row.effect == EffectSlideToNote) { - channel_state->frequency_target = note_to_freq(row.note); - } else { - channel_state->frequency = note_to_freq(row.note); - channel_state->frequency_target = FREQUENCY_UNSET; - } - } - } - - if(channel_state->play) { - float frequency, pwm; - - if((row.effect == EffectSlideUp || row.effect == EffectSlideDown) && - row.data != EFFECT_DATA_NONE) { - // apply slide effect - channel_state->frequency += (row.effect == EffectSlideUp ? 1 : -1) * row.data; - } else if(row.effect == EffectSlideToNote) { - // apply slide to note effect, if target frequency is set - if(channel_state->frequency_target > 0) { - if(channel_state->frequency_target > channel_state->frequency) { - channel_state->frequency += row.data; - if(channel_state->frequency > channel_state->frequency_target) { - channel_state->frequency = channel_state->frequency_target; - channel_state->frequency_target = FREQUENCY_UNSET; - } - } else if(channel_state->frequency_target < channel_state->frequency) { - channel_state->frequency -= row.data; - if(channel_state->frequency < channel_state->frequency_target) { - channel_state->frequency = channel_state->frequency_target; - channel_state->frequency_target = FREQUENCY_UNSET; - } - } - } - } - - frequency = channel_state->frequency; - pwm = channel_state->pwm; - - // apply arpeggio effect - if(row.effect == EffectArpeggio) { - if(row.data != EFFECT_DATA_NONE) { - if((song_state->tick % 3) == 1) { - uint8_t note_offset = EFFECT_DATA_GET_X(row.data); - frequency = frequency_offset_semitones(frequency, note_offset); - } else if((song_state->tick % 3) == 2) { - uint8_t note_offset = EFFECT_DATA_GET_Y(row.data); - frequency = frequency_offset_semitones(frequency, note_offset); - } - } - } else if(row.effect == EffectVibrato) { - // apply vibrato effect, data = speed, depth - uint8_t vibrato_speed = EFFECT_DATA_GET_X(row.data); - uint8_t vibrato_depth = EFFECT_DATA_GET_Y(row.data); - - // update vibrato parameters if speed or depth is non-zero - if(vibrato_speed != 0) channel_state->vibrato.speed = vibrato_speed; - if(vibrato_depth != 0) channel_state->vibrato.depth = vibrato_depth; - - // update vibrato value - channel_state->vibrato.value += - channel_state->vibrato.direction * channel_state->vibrato.speed; - - // change direction if value is at the limit - if(channel_state->vibrato.value > channel_state->vibrato.depth) { - channel_state->vibrato.direction = -1; - } else if(channel_state->vibrato.value < -channel_state->vibrato.depth) { - channel_state->vibrato.direction = 1; - } else if(channel_state->vibrato.direction == 0) { - // set initial direction, if it is not set - channel_state->vibrato.direction = 1; - } - - frequency += - (frequency_get_seventh_of_a_semitone(frequency) * channel_state->vibrato.value); - } else if(row.effect == EffectPWM) { - pwm = (pwm - PWM_MIN) / EFFECT_DATA_1_MAX * row.data + PWM_MIN; - } - - tracker_speaker_play(frequency, pwm); - } else { - tracker_speaker_stop(); - } - - song_state->tick++; - if(song_state->tick >= song_state->tick_limit) { - song_state->tick = 0; - - // next note - song_state->row_index = (song_state->row_index + 1); - - if(song_state->row_index >= PATTERN_SIZE) { - int16_t next_pattern_index = - advance_order_and_get_next_pattern_index(song, song_state); - advance_to_pattern( - tracker, - (Location){ - .pattern = next_pattern_index, - .change_pattern = true, - }); - } else { - tracker_send_position_message(tracker); - } - } -} - -static void tracker_interrupt_cb(void* context) { - Tracker* tracker = (Tracker*)context; - tracker_debug_set(true); - tracker_interrupt_body(tracker); - tracker_debug_set(false); -} - -/********************************************************************* - * Tracker Interface - *********************************************************************/ - -Tracker* tracker_alloc() { - Tracker* tracker = malloc(sizeof(Tracker)); - return tracker; -} - -void tracker_free(Tracker* tracker) { - tracker_song_state_clear(tracker); - free(tracker); -} - -void tracker_set_message_callback(Tracker* tracker, TrackerMessageCallback callback, void* context) { - furi_check(tracker->playing == false); - tracker->callback = callback; - tracker->context = context; -} - -void tracker_set_song(Tracker* tracker, const Song* song) { - furi_check(tracker->playing == false); - tracker->song = song; - tracker_song_state_init(tracker); -} - -void tracker_set_order_index(Tracker* tracker, uint8_t order_index) { - furi_check(tracker->playing == false); - furi_check(order_index < tracker->song->order_list_size); - tracker->song_state.order_list_index = order_index; - tracker->song_state.pattern_index = tracker->song->order_list[order_index]; -} - -void tracker_set_row(Tracker* tracker, uint8_t row) { - furi_check(tracker->playing == false); - furi_check(row < PATTERN_SIZE); - tracker->song_state.row_index = row; -} - -void tracker_start(Tracker* tracker) { - furi_check(tracker->song != NULL); - - tracker->playing = true; - tracker_send_position_message(tracker); - tracker_debug_init(); - tracker_speaker_init(); - tracker_interrupt_init(tracker->song->ticks_per_second, tracker_interrupt_cb, tracker); -} - -void tracker_stop(Tracker* tracker) { - tracker_interrupt_deinit(); - tracker_speaker_deinit(); - tracker_debug_deinit(); - - tracker->playing = false; -} \ No newline at end of file diff --git a/applications/external/music_tracker/tracker_engine/tracker.h b/applications/external/music_tracker/tracker_engine/tracker.h deleted file mode 100644 index 70bf4bd6b..000000000 --- a/applications/external/music_tracker/tracker_engine/tracker.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once -#include "tracker_notes.h" -#include "tracker_song.h" - -typedef enum { - TrackerPositionChanged, - TrackerEndOfSong, -} TrackerMessageType; - -typedef struct { - TrackerMessageType type; - union tracker_message_data { - struct { - uint8_t order_list_index; - uint8_t row; - } position; - } data; -} TrackerMessage; - -typedef void (*TrackerMessageCallback)(TrackerMessage message, void* context); - -typedef struct Tracker Tracker; - -Tracker* tracker_alloc(); - -void tracker_free(Tracker* tracker); - -void tracker_set_message_callback(Tracker* tracker, TrackerMessageCallback callback, void* context); - -void tracker_set_song(Tracker* tracker, const Song* song); - -void tracker_set_order_index(Tracker* tracker, uint8_t order_index); - -void tracker_set_row(Tracker* tracker, uint8_t row); - -void tracker_start(Tracker* tracker); - -void tracker_stop(Tracker* tracker); \ No newline at end of file diff --git a/applications/external/music_tracker/tracker_engine/tracker_notes.h b/applications/external/music_tracker/tracker_engine/tracker_notes.h deleted file mode 100644 index 22ab3590f..000000000 --- a/applications/external/music_tracker/tracker_engine/tracker_notes.h +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once - -#define NOTE_NONE 0 -#define NOTE_C2 1 -#define NOTE_Cs2 2 -#define NOTE_D2 3 -#define NOTE_Ds2 4 -#define NOTE_E2 5 -#define NOTE_F2 6 -#define NOTE_Fs2 7 -#define NOTE_G2 8 -#define NOTE_Gs2 9 -#define NOTE_A2 10 -#define NOTE_As2 11 -#define NOTE_B2 12 -#define NOTE_C3 13 -#define NOTE_Cs3 14 -#define NOTE_D3 15 -#define NOTE_Ds3 16 -#define NOTE_E3 17 -#define NOTE_F3 18 -#define NOTE_Fs3 19 -#define NOTE_G3 20 -#define NOTE_Gs3 21 -#define NOTE_A3 22 -#define NOTE_As3 23 -#define NOTE_B3 24 -#define NOTE_C4 25 -#define NOTE_Cs4 26 -#define NOTE_D4 27 -#define NOTE_Ds4 28 -#define NOTE_E4 29 -#define NOTE_F4 30 -#define NOTE_Fs4 31 -#define NOTE_G4 32 -#define NOTE_Gs4 33 -#define NOTE_A4 34 -#define NOTE_As4 35 -#define NOTE_B4 36 -#define NOTE_C5 37 -#define NOTE_Cs5 38 -#define NOTE_D5 39 -#define NOTE_Ds5 40 -#define NOTE_E5 41 -#define NOTE_F5 42 -#define NOTE_Fs5 43 -#define NOTE_G5 44 -#define NOTE_Gs5 45 -#define NOTE_A5 46 -#define NOTE_As5 47 -#define NOTE_B5 48 -#define NOTE_C6 49 -#define NOTE_Cs6 50 -#define NOTE_D6 51 -#define NOTE_Ds6 52 -#define NOTE_E6 53 -#define NOTE_F6 54 -#define NOTE_Fs6 55 -#define NOTE_G6 56 -#define NOTE_Gs6 57 -#define NOTE_A6 58 -#define NOTE_As6 59 -#define NOTE_B6 60 -#define NOTE_OFF 63 \ No newline at end of file diff --git a/applications/external/music_tracker/tracker_engine/tracker_song.h b/applications/external/music_tracker/tracker_engine/tracker_song.h deleted file mode 100644 index 7a054f7b1..000000000 --- a/applications/external/music_tracker/tracker_engine/tracker_song.h +++ /dev/null @@ -1,109 +0,0 @@ -#pragma once -#include - -/** - * @brief Row - * - * AH AL - * FEDCBA98 76543210 - * nnnnnnee eedddddd - * -------- -------- - * nnnnnn = [0] do nothing, [1..60] note number, [61] note off, [62..63] not used - * ee ee = [0..F] effect - * 111222 = [0..63] or [0..7, 0..7] effect data - */ -typedef uint16_t Row; - -#define ROW_NOTE_MASK 0x3F -#define ROW_EFFECT_MASK 0x0F -#define ROW_EFFECT_DATA_MASK 0x3F - -typedef enum { - // 0xy, x - first semitones offset, y - second semitones offset. 0 - no offset .. 7 - +7 semitones... - // Play the arpeggio chord with three notes. The first note is the base note, the second and third are offset by x and y. - // Each note plays one tick. - EffectArpeggio = 0x00, - - // 1xx, xx - effect speed, 0 - no effect, 1 - slowest, 0x3F - fastest. - // Slide the note pitch up by xx Hz every tick. - EffectSlideUp = 0x01, - - // 2xx, xx - effect speed, 0 - no effect, 1 - slowest, 0x3F - fastest. - // Slide the note pitch down by xx Hz every tick. - EffectSlideDown = 0x02, - - // 3xx, xx - effect speed, 0 - no effect, 1 - slowest, 0x3F - fastest. - // Slide the already playing note pitch towards another one by xx Hz every tick. - // The note value is saved until the note is playing, so you don't have to repeat the note value to continue sliding. - EffectSlideToNote = 0x03, - - // 4xy, x - vibrato speed (0..7), y - vibrato depth (0..7). - // Vibrato effect. The pitch of the note increases by x Hz each tick to a positive vibrato depth, then decreases to a negative depth. - // Value 1 of depth means 1/7 of a semitone (about 14.28 ct), so value 7 means full semitone. - // Note will play without vibrato on the first tick at the beginning of the effect. - // Vibrato speed and depth are saved until the note is playing, and will be updated only if they are not zero, so you doesn't have to repeat them every tick. - EffectVibrato = 0x04, - - // Effect05 = 0x05, - // Effect06 = 0x06, - // Effect07 = 0x07, - // Effect08 = 0x08, - // Effect09 = 0x09, - // Effect0A = 0x0A, - - // Bxx, xx - pattern number - // Jump to the order xx in the pattern order table at first tick of current row. - // So if you want to jump to the pattern after note 4, you should put this effect on the 5th note. - EffectJumpToOrder = 0x0B, - - // Cxx, xx - pwm value - // Set the PWM value to xx for current row. - EffectPWM = 0x0C, - - // Bxx, xx - row number - // Jump to the row xx in next pattern at first tick of current row. - // So if you want to jump to the pattern after note 4, you should put this effect on the 5th note. - EffectBreakPattern = 0x0D, - - // Effect0E = 0x0E, - - // Fxx, xx - song speed, 0 - 1 tick per note, 1 - 2 ticks per note, 0x3F - 64 ticks per note. - // Set the speed of the song in terms of ticks per note. - // Will be applied at the first tick of current row. - EffectSetSpeed = 0x0F, -} Effect; - -#define EFFECT_DATA_2(x, y) ((x) | ((y) << 3)) -#define EFFECT_DATA_GET_X(data) ((data)&0x07) -#define EFFECT_DATA_GET_Y(data) (((data) >> 3) & 0x07) -#define EFFECT_DATA_NONE 0 -#define EFFECT_DATA_1_MAX 0x3F -#define EFFECT_DATA_2_MAX 0x07 - -#define FREQUENCY_UNSET -1.0f - -#define PWM_MIN 0.01f -#define PWM_MAX 0.5f -#define PWM_DEFAULT PWM_MAX - -#define PATTERN_SIZE 64 - -#define ROW_MAKE(note, effect, data) \ - ((Row)(((note)&0x3F) | (((effect)&0xF) << 6) | (((data)&0x3F) << 10))) - -typedef struct { - Row rows[PATTERN_SIZE]; -} Channel; - -typedef struct { - Channel* channels; -} Pattern; - -typedef struct { - uint8_t channels_count; - uint8_t patterns_count; - Pattern* patterns; - uint8_t order_list_size; - uint8_t* order_list; - uint16_t ticks_per_second; -} Song; \ No newline at end of file diff --git a/applications/external/music_tracker/view/tracker_view.c b/applications/external/music_tracker/view/tracker_view.c deleted file mode 100644 index 87e6b0fcf..000000000 --- a/applications/external/music_tracker/view/tracker_view.c +++ /dev/null @@ -1,182 +0,0 @@ -#include "tracker_view.h" -#include -#include - -typedef struct { - const Song* song; - uint8_t order_list_index; - uint8_t row; -} TrackerViewModel; - -struct TrackerView { - View* view; - void* back_context; - TrackerViewCallback back_callback; -}; - -static Channel* get_current_channel(TrackerViewModel* model) { - uint8_t channel_id = 0; - uint8_t pattern_id = model->song->order_list[model->order_list_index]; - Pattern* pattern = &model->song->patterns[pattern_id]; - return &pattern->channels[channel_id]; -} - -static const char* get_note_from_id(uint8_t note) { -#define NOTE_COUNT 12 - const char* notes[NOTE_COUNT] = { - "C ", - "C#", - "D ", - "D#", - "E ", - "F ", - "F#", - "G ", - "G#", - "A ", - "A#", - "B ", - }; - return notes[(note) % NOTE_COUNT]; -#undef NOTE_COUNT -} - -static uint8_t get_octave_from_id(uint8_t note) { - return ((note) / 12) + 2; -} - -static uint8_t get_first_row_id(uint8_t row) { - return (row / 10) * 10; -} - -static void - draw_row(Canvas* canvas, uint8_t i, Channel* channel, uint8_t row, FuriString* buffer) { - uint8_t x = 12 * (i + 1); - uint8_t first_row_id = get_first_row_id(row); - uint8_t current_row_id = first_row_id + i; - - if((current_row_id) >= 64) { - return; - } - - Row current_row = channel->rows[current_row_id]; - uint8_t note = current_row & ROW_NOTE_MASK; - uint8_t effect = (current_row >> 6) & ROW_EFFECT_MASK; - uint8_t data = (current_row >> 10) & ROW_EFFECT_DATA_MASK; - - if(current_row_id == row) { - canvas_set_color(canvas, ColorBlack); - canvas_draw_line(canvas, x - 9, 1, x - 9, 62); - canvas_draw_box(canvas, x - 8, 0, 9, 64); - canvas_draw_line(canvas, x + 1, 1, x + 1, 62); - canvas_set_color(canvas, ColorWhite); - } - - furi_string_printf(buffer, "%02X", current_row_id); - canvas_draw_str(canvas, x, 61, furi_string_get_cstr(buffer)); - - if(note > 0 && note < NOTE_OFF) { - furi_string_printf( - buffer, "%s%d", get_note_from_id(note - 1), get_octave_from_id(note - 1)); - canvas_draw_str(canvas, x, 44, furi_string_get_cstr(buffer)); - } else if(note == NOTE_OFF) { - canvas_draw_str(canvas, x, 44, "OFF"); - } else { - canvas_draw_str(canvas, x, 44, "---"); - } - - if(effect == 0 && data == 0) { - canvas_draw_str(canvas, x, 21, "-"); - canvas_draw_str(canvas, x, 12, "--"); - } else { - furi_string_printf(buffer, "%X", effect); - canvas_draw_str(canvas, x, 21, furi_string_get_cstr(buffer)); - - if(effect == EffectArpeggio || effect == EffectVibrato) { - uint8_t data_x = EFFECT_DATA_GET_X(data); - uint8_t data_y = EFFECT_DATA_GET_Y(data); - furi_string_printf(buffer, "%d%d", data_x, data_y); - canvas_draw_str(canvas, x, 12, furi_string_get_cstr(buffer)); - } else { - furi_string_printf(buffer, "%02X", data); - canvas_draw_str(canvas, x, 12, furi_string_get_cstr(buffer)); - } - } - - if(current_row_id == row) { - canvas_set_color(canvas, ColorBlack); - } -} - -static void tracker_view_draw_callback(Canvas* canvas, void* _model) { - TrackerViewModel* model = _model; - if(model->song == NULL) { - return; - } - - canvas_set_font_direction(canvas, CanvasDirectionBottomToTop); - canvas_set_font(canvas, FontKeyboard); - - Channel* channel = get_current_channel(model); - FuriString* buffer = furi_string_alloc(); - - for(uint8_t i = 0; i < 10; i++) { - draw_row(canvas, i, channel, model->row, buffer); - } - furi_string_free(buffer); -} - -static bool tracker_view_input_callback(InputEvent* event, void* context) { - TrackerView* tracker_view = context; - - if(tracker_view->back_callback) { - if(event->type == InputTypeShort && event->key == InputKeyBack) { - tracker_view->back_callback(tracker_view->back_context); - return true; - } - } - return false; -} - -TrackerView* tracker_view_alloc() { - TrackerView* tracker_view = malloc(sizeof(TrackerView)); - tracker_view->view = view_alloc(); - view_allocate_model(tracker_view->view, ViewModelTypeLocking, sizeof(TrackerViewModel)); - view_set_context(tracker_view->view, tracker_view); - view_set_draw_callback(tracker_view->view, (ViewDrawCallback)tracker_view_draw_callback); - view_set_input_callback(tracker_view->view, (ViewInputCallback)tracker_view_input_callback); - return tracker_view; -} - -void tracker_view_free(TrackerView* tracker_view) { - view_free(tracker_view->view); - free(tracker_view); -} - -View* tracker_view_get_view(TrackerView* tracker_view) { - return tracker_view->view; -} - -void tracker_view_set_back_callback( - TrackerView* tracker_view, - TrackerViewCallback callback, - void* context) { - tracker_view->back_callback = callback; - tracker_view->back_context = context; -} - -void tracker_view_set_song(TrackerView* tracker_view, const Song* song) { - with_view_model( - tracker_view->view, TrackerViewModel * model, { model->song = song; }, true); -} - -void tracker_view_set_position(TrackerView* tracker_view, uint8_t order_list_index, uint8_t row) { - with_view_model( - tracker_view->view, - TrackerViewModel * model, - { - model->order_list_index = order_list_index; - model->row = row; - }, - true); -} \ No newline at end of file diff --git a/applications/external/music_tracker/view/tracker_view.h b/applications/external/music_tracker/view/tracker_view.h deleted file mode 100644 index 6c2e69ba4..000000000 --- a/applications/external/music_tracker/view/tracker_view.h +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include "../tracker_engine/tracker.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct TrackerView TrackerView; - -TrackerView* tracker_view_alloc(); - -void tracker_view_free(TrackerView* tracker_view); - -View* tracker_view_get_view(TrackerView* tracker_view); - -typedef void (*TrackerViewCallback)(void* context); - -void tracker_view_set_back_callback( - TrackerView* tracker_view, - TrackerViewCallback callback, - void* context); - -void tracker_view_set_song(TrackerView* tracker_view, const Song* song); - -void tracker_view_set_position(TrackerView* tracker_view, uint8_t order_list_index, uint8_t row); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/applications/external/music_tracker/zero_tracker.c b/applications/external/music_tracker/zero_tracker.c deleted file mode 100644 index f4c10d9ef..000000000 --- a/applications/external/music_tracker/zero_tracker.c +++ /dev/null @@ -1,536 +0,0 @@ -#include -#include -#include -#include -#include "zero_tracker.h" -#include "tracker_engine/tracker.h" -#include "view/tracker_view.h" - -// Channel p_0_channels[] = { -// { -// .rows = -// { -// // 1/4 -// ROW_MAKE(NOTE_C3, EffectArpeggio, EFFECT_DATA_2(4, 7)), -// ROW_MAKE(0, EffectArpeggio, EFFECT_DATA_2(4, 7)), -// ROW_MAKE(NOTE_C4, EffectSlideToNote, 0x20), -// ROW_MAKE(0, EffectSlideToNote, 0x20), -// // -// ROW_MAKE(0, EffectSlideToNote, 0x20), -// ROW_MAKE(0, EffectSlideToNote, 0x20), -// ROW_MAKE(0, EffectSlideToNote, 0x20), -// ROW_MAKE(0, EffectSlideToNote, 0x20), -// // -// ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(1, 1)), -// ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(1, 1)), -// ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(1, 1)), -// ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(1, 1)), -// // -// ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(2, 2)), -// ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(2, 2)), -// ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(2, 2)), -// ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(2, 2)), -// // 2/4 -// ROW_MAKE(NOTE_C3, EffectSlideDown, 0x20), -// ROW_MAKE(0, EffectSlideDown, 0x20), -// ROW_MAKE(NOTE_C4, EffectVibrato, EFFECT_DATA_2(3, 3)), -// ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(3, 3)), -// // -// ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(3, 3)), -// ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(3, 3)), -// ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(3, 3)), -// ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(3, 3)), -// // -// ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(3, 3)), -// ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(3, 3)), -// ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(3, 3)), -// ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(3, 3)), -// // -// ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(3, 3)), -// ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(3, 3)), -// ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(3, 3)), -// ROW_MAKE(NOTE_OFF, EffectVibrato, EFFECT_DATA_2(3, 3)), -// // 3/4 -// ROW_MAKE(NOTE_C3, EffectArpeggio, EFFECT_DATA_2(4, 7)), -// ROW_MAKE(0, EffectArpeggio, EFFECT_DATA_2(4, 7)), -// ROW_MAKE(NOTE_OFF, 0, 0), -// ROW_MAKE(0, 0, 0), -// // -// ROW_MAKE(0, 0, 0), -// ROW_MAKE(0, 0, 0), -// ROW_MAKE(0, 0, 0), -// ROW_MAKE(0, 0, 0), -// // -// ROW_MAKE(NOTE_C2, EffectPWM, 60), -// ROW_MAKE(0, EffectPWM, 32), -// ROW_MAKE(0, EffectPWM, 12), -// ROW_MAKE(NOTE_OFF, 0, 0), -// // -// ROW_MAKE(0, 0, 0), -// ROW_MAKE(0, 0, 0), -// ROW_MAKE(0, 0, 0), -// ROW_MAKE(0, 0, 0), -// // 4/4 -// ROW_MAKE(NOTE_C3, EffectSlideDown, 0x20), -// ROW_MAKE(0, EffectSlideDown, 0x20), -// ROW_MAKE(0, EffectSlideDown, 0x20), -// ROW_MAKE(NOTE_OFF, 0, 0), -// // -// ROW_MAKE(0, 0, 0), -// ROW_MAKE(0, 0, 0), -// ROW_MAKE(0, 0, 0), -// ROW_MAKE(0, 0, 0), -// // -// ROW_MAKE(NOTE_C2, EffectPWM, 60), -// ROW_MAKE(0, EffectPWM, 32), -// ROW_MAKE(0, EffectPWM, 12), -// ROW_MAKE(NOTE_OFF, 0, 0), -// // -// ROW_MAKE(0, 0, 0), -// ROW_MAKE(0, 0, 0), -// ROW_MAKE(0, 0, 0), -// ROW_MAKE(0, 0, 0), -// }, -// }, -// }; - -Channel p_0_channels[] = { - { - .rows = - { - // - ROW_MAKE(NOTE_A4, EffectArpeggio, EFFECT_DATA_2(4, 7)), - ROW_MAKE(NOTE_C3, 0, 0), - ROW_MAKE(NOTE_F2, 0, 0), - ROW_MAKE(NOTE_C3, 0, 0), - // - ROW_MAKE(NOTE_E4, 0, 0), - ROW_MAKE(NOTE_C3, 0, 0), - ROW_MAKE(NOTE_E4, EffectPWM, 50), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_A4, 0, 0), - ROW_MAKE(0, EffectPWM, 55), - ROW_MAKE(0, EffectPWM, 45), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_E5, 0, 0), - ROW_MAKE(0, EffectPWM, 55), - ROW_MAKE(0, EffectPWM, 45), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_D5, 0, 0), - ROW_MAKE(NOTE_C3, EffectSlideDown, 0x30), - ROW_MAKE(NOTE_F2, 0, 0), - ROW_MAKE(NOTE_C3, 0, 0), - // - ROW_MAKE(NOTE_C5, 0, 0), - ROW_MAKE(NOTE_C3, 0, 0), - ROW_MAKE(NOTE_C5, 0, 0), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_A4, 0, 0), - ROW_MAKE(0, 0, 0), - ROW_MAKE(0, 0, 0), - ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(1, 1)), - // - ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(1, 1)), - ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(2, 2)), - ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(2, 2)), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_B4, EffectArpeggio, EFFECT_DATA_2(4, 7)), - ROW_MAKE(NOTE_D3, 0, 0), - ROW_MAKE(NOTE_G2, 0, 0), - ROW_MAKE(NOTE_D3, 0, 0), - // - ROW_MAKE(NOTE_E4, 0, 0), - ROW_MAKE(NOTE_D3, 0, 0), - ROW_MAKE(NOTE_E4, EffectPWM, 50), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_A4, 0, 0), - ROW_MAKE(0, EffectPWM, 55), - ROW_MAKE(0, EffectPWM, 45), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_E5, 0, 0), - ROW_MAKE(0, EffectPWM, 55), - ROW_MAKE(0, EffectPWM, 45), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_D5, 0, 0), - ROW_MAKE(NOTE_D3, EffectSlideDown, 0x3F), - ROW_MAKE(NOTE_G2, 0, 0), - ROW_MAKE(NOTE_D3, 0, 0), - // - ROW_MAKE(NOTE_C5, 0, 0), - ROW_MAKE(NOTE_D3, 0, 0), - ROW_MAKE(NOTE_C5, 0, 0), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_A4, 0, 0), - ROW_MAKE(0, 0, 0), - ROW_MAKE(0, 0, 0), - ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(1, 1)), - // - ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(1, 1)), - ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(2, 2)), - ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(2, 2)), - ROW_MAKE(NOTE_OFF, 0, 0), - }, - }, -}; - -Channel p_1_channels[] = { - { - .rows = - { - // - ROW_MAKE(NOTE_C5, EffectArpeggio, EFFECT_DATA_2(4, 7)), - ROW_MAKE(NOTE_E3, 0, 0), - ROW_MAKE(NOTE_A2, 0, 0), - ROW_MAKE(NOTE_E3, 0, 0), - // - ROW_MAKE(NOTE_B4, 0, 0), - ROW_MAKE(NOTE_E3, 0, 0), - ROW_MAKE(NOTE_B4, EffectPWM, 50), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_G4, 0, 0), - ROW_MAKE(0, EffectPWM, 55), - ROW_MAKE(0, EffectPWM, 45), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_C5, 0, 0), - ROW_MAKE(0, EffectPWM, 55), - ROW_MAKE(0, EffectPWM, 45), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_C6, 0, 0), - ROW_MAKE(NOTE_E3, EffectSlideDown, 0x30), - ROW_MAKE(NOTE_A2, 0, 0), - ROW_MAKE(NOTE_E3, 0, 0), - // - ROW_MAKE(NOTE_B4, 0, 0), - ROW_MAKE(NOTE_E3, 0, 0), - ROW_MAKE(NOTE_B4, EffectPWM, 50), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_G4, 0, 0), - ROW_MAKE(0, 0, 0), - ROW_MAKE(0, 0, 0), - ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(1, 1)), - // - ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(1, 1)), - ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(2, 2)), - ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(2, 2)), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_C5, EffectArpeggio, EFFECT_DATA_2(4, 7)), - ROW_MAKE(NOTE_E3, 0, 0), - ROW_MAKE(NOTE_A2, 0, 0), - ROW_MAKE(NOTE_E3, 0, 0), - // - ROW_MAKE(NOTE_B4, 0, 0), - ROW_MAKE(NOTE_E3, 0, 0), - ROW_MAKE(NOTE_B4, EffectPWM, 50), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_G4, 0, 0), - ROW_MAKE(0, EffectPWM, 55), - ROW_MAKE(0, EffectPWM, 45), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_D5, 0, 0), - ROW_MAKE(0, EffectPWM, 55), - ROW_MAKE(0, EffectPWM, 45), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_C6, 0, 0), - ROW_MAKE(NOTE_E3, EffectSlideDown, 0x30), - ROW_MAKE(NOTE_A2, 0, 0), - ROW_MAKE(NOTE_E3, 0, 0), - // - ROW_MAKE(NOTE_B4, 0, 0), - ROW_MAKE(NOTE_E3, 0, 0), - ROW_MAKE(NOTE_B4, EffectPWM, 50), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_G4, 0, 0), - ROW_MAKE(0, 0, 0), - ROW_MAKE(0, 0, 0), - ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(1, 1)), - // - ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(1, 1)), - ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(2, 2)), - ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(2, 2)), - ROW_MAKE(NOTE_OFF, 0, 0), - }, - }, -}; - -Channel p_2_channels[] = { - { - .rows = - { - // - ROW_MAKE(NOTE_C5, EffectArpeggio, EFFECT_DATA_2(4, 7)), - ROW_MAKE(NOTE_E3, 0, 0), - ROW_MAKE(NOTE_A2, 0, 0), - ROW_MAKE(NOTE_E3, 0, 0), - // - ROW_MAKE(NOTE_C5, 0, 0), - ROW_MAKE(NOTE_A4, 0, 0), - ROW_MAKE(NOTE_C5, 0, 0), - ROW_MAKE(NOTE_A4, 0, 0), - // - ROW_MAKE(NOTE_C5, EffectPWM, 55), - ROW_MAKE(NOTE_A4, EffectPWM, 45), - ROW_MAKE(NOTE_C5, EffectPWM, 35), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_C5, 0, 0), - ROW_MAKE(NOTE_A4, 0, 0), - ROW_MAKE(NOTE_C5, EffectPWM, 55), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_D5, 0, 0), - ROW_MAKE(NOTE_E3, EffectSlideDown, 0x30), - ROW_MAKE(NOTE_A2, 0, 0), - ROW_MAKE(NOTE_E3, 0, 0), - // - ROW_MAKE(NOTE_OFF, 0, 0), - ROW_MAKE(NOTE_E3, 0, 0), - ROW_MAKE(NOTE_B4, EffectPWM, 55), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_D5, 0, 0), - ROW_MAKE(NOTE_B4, 0, 0), - ROW_MAKE(NOTE_D5, EffectPWM, 55), - ROW_MAKE(NOTE_B4, EffectPWM, 55), - // - ROW_MAKE(NOTE_D5, EffectPWM, 45), - ROW_MAKE(NOTE_B4, EffectPWM, 45), - ROW_MAKE(NOTE_D5, EffectPWM, 35), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_D5, EffectArpeggio, EFFECT_DATA_2(4, 7)), - ROW_MAKE(NOTE_E3, 0, 0), - ROW_MAKE(NOTE_A2, 0, 0), - ROW_MAKE(NOTE_E3, 0, 0), - // - ROW_MAKE(NOTE_E5, 0, 0), - ROW_MAKE(NOTE_C5, 0, 0), - ROW_MAKE(NOTE_E5, 0, 0), - ROW_MAKE(NOTE_C5, 0, 0), - // - ROW_MAKE(NOTE_E5, EffectPWM, 55), - ROW_MAKE(NOTE_C5, EffectPWM, 45), - ROW_MAKE(NOTE_E5, EffectPWM, 35), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_E5, 0, 0), - ROW_MAKE(NOTE_C5, 0, 0), - ROW_MAKE(NOTE_E5, EffectPWM, 55), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_D5, 0, 0), - ROW_MAKE(NOTE_E3, EffectSlideDown, 0x30), - ROW_MAKE(NOTE_A2, 0, 0), - ROW_MAKE(NOTE_E3, 0, 0), - // - ROW_MAKE(NOTE_OFF, 0, 0), - ROW_MAKE(NOTE_E3, 0, 0), - ROW_MAKE(NOTE_B4, EffectPWM, 55), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_D5, 0, 0), - ROW_MAKE(NOTE_B4, 0, 0), - ROW_MAKE(NOTE_D5, EffectPWM, 55), - ROW_MAKE(NOTE_B4, EffectPWM, 55), - // - ROW_MAKE(NOTE_D5, EffectPWM, 45), - ROW_MAKE(NOTE_B4, EffectPWM, 45), - ROW_MAKE(NOTE_D5, EffectPWM, 35), - ROW_MAKE(NOTE_OFF, 0, 0), - }, - }, -}; - -Channel p_3_channels[] = { - { - .rows = - { - // - ROW_MAKE(NOTE_Ds5, EffectArpeggio, EFFECT_DATA_2(4, 6)), - ROW_MAKE(NOTE_C5, 0, 0), - ROW_MAKE(NOTE_Ds5, 0, 0), - ROW_MAKE(NOTE_C5, EffectPWM, 55), - // - ROW_MAKE(NOTE_Ds5, EffectPWM, 45), - ROW_MAKE(NOTE_C5, EffectPWM, 35), - ROW_MAKE(NOTE_Ds5, EffectPWM, 30), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_D5, 0, 0), - ROW_MAKE(NOTE_B4, 0, 0), - ROW_MAKE(NOTE_D5, 0, 0), - ROW_MAKE(NOTE_B4, EffectPWM, 55), - // - ROW_MAKE(NOTE_D5, EffectPWM, 45), - ROW_MAKE(NOTE_B4, EffectPWM, 35), - ROW_MAKE(NOTE_D5, EffectPWM, 30), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_Cs5, EffectArpeggio, EFFECT_DATA_2(4, 6)), - ROW_MAKE(NOTE_As4, 0, 0), - ROW_MAKE(NOTE_Cs5, 0, 0), - ROW_MAKE(NOTE_As4, EffectPWM, 55), - // - ROW_MAKE(NOTE_Cs5, EffectPWM, 45), - ROW_MAKE(NOTE_As4, EffectPWM, 35), - ROW_MAKE(NOTE_Cs5, EffectPWM, 30), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_C5, 0, 0), - ROW_MAKE(NOTE_A4, 0, 0), - ROW_MAKE(NOTE_C5, 0, 0), - ROW_MAKE(NOTE_A4, EffectPWM, 55), - // - ROW_MAKE(NOTE_C5, EffectPWM, 45), - ROW_MAKE(NOTE_A4, EffectPWM, 35), - ROW_MAKE(NOTE_C5, EffectPWM, 30), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_B4, EffectArpeggio, EFFECT_DATA_2(4, 6)), - ROW_MAKE(NOTE_Gs4, 0, 0), - ROW_MAKE(NOTE_B4, 0, 0), - ROW_MAKE(NOTE_Gs4, EffectPWM, 55), - // - ROW_MAKE(NOTE_B4, EffectPWM, 45), - ROW_MAKE(NOTE_Gs4, EffectPWM, 35), - ROW_MAKE(NOTE_B4, EffectPWM, 30), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_C5, 0, 0), - ROW_MAKE(NOTE_A4, 0, 0), - ROW_MAKE(NOTE_C5, 0, 0), - ROW_MAKE(NOTE_A4, EffectPWM, 55), - // - ROW_MAKE(NOTE_C5, EffectPWM, 45), - ROW_MAKE(NOTE_A4, EffectPWM, 35), - ROW_MAKE(NOTE_C5, EffectPWM, 30), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_Cs5, EffectArpeggio, EFFECT_DATA_2(4, 6)), - ROW_MAKE(NOTE_As4, 0, 0), - ROW_MAKE(NOTE_Cs5, 0, 0), - ROW_MAKE(NOTE_As4, EffectPWM, 55), - // - ROW_MAKE(NOTE_Cs5, EffectPWM, 45), - ROW_MAKE(NOTE_As4, EffectPWM, 35), - ROW_MAKE(NOTE_Cs5, EffectPWM, 30), - ROW_MAKE(NOTE_OFF, 0, 0), - // - ROW_MAKE(NOTE_D5, 0, 0), - ROW_MAKE(NOTE_B4, 0, 0), - ROW_MAKE(NOTE_D5, 0, 0), - ROW_MAKE(NOTE_B4, EffectPWM, 55), - // - ROW_MAKE(NOTE_D5, EffectPWM, 45), - ROW_MAKE(NOTE_B4, EffectPWM, 35), - ROW_MAKE(NOTE_D5, EffectPWM, 30), - ROW_MAKE(NOTE_OFF, 0, 0), - }, - }, -}; -Pattern patterns[] = { - {.channels = p_0_channels}, - {.channels = p_1_channels}, - {.channels = p_2_channels}, - {.channels = p_3_channels}, -}; - -uint8_t order_list[] = { - 0, - 1, - 0, - 2, - 0, - 1, - 0, - 3, -}; - -Song song = { - .channels_count = 1, - .patterns_count = sizeof(patterns) / sizeof(patterns[0]), - .patterns = patterns, - - .order_list_size = sizeof(order_list) / sizeof(order_list[0]), - .order_list = order_list, - - .ticks_per_second = 60, -}; - -void tracker_message(TrackerMessage message, void* context) { - FuriMessageQueue* queue = context; - furi_assert(queue); - furi_message_queue_put(queue, &message, 0); -} - -int32_t zero_tracker_app(void* p) { - UNUSED(p); - - NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); - notification_message(notification, &sequence_display_backlight_enforce_on); - - Gui* gui = furi_record_open(RECORD_GUI); - ViewDispatcher* view_dispatcher = view_dispatcher_alloc(); - TrackerView* tracker_view = tracker_view_alloc(); - tracker_view_set_song(tracker_view, &song); - view_dispatcher_add_view(view_dispatcher, 0, tracker_view_get_view(tracker_view)); - view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen); - view_dispatcher_switch_to_view(view_dispatcher, 0); - - FuriMessageQueue* queue = furi_message_queue_alloc(8, sizeof(TrackerMessage)); - Tracker* tracker = tracker_alloc(); - tracker_set_message_callback(tracker, tracker_message, queue); - tracker_set_song(tracker, &song); - tracker_start(tracker); - - while(1) { - TrackerMessage message; - FuriStatus status = furi_message_queue_get(queue, &message, portMAX_DELAY); - if(status == FuriStatusOk) { - if(message.type == TrackerPositionChanged) { - uint8_t order_list_index = message.data.position.order_list_index; - uint8_t row = message.data.position.row; - uint8_t pattern = song.order_list[order_list_index]; - tracker_view_set_position(tracker_view, order_list_index, row); - FURI_LOG_I("Tracker", "O:%d P:%d R:%d", order_list_index, pattern, row); - } else if(message.type == TrackerEndOfSong) { - FURI_LOG_I("Tracker", "End of song"); - break; - } - } - } - - tracker_stop(tracker); - tracker_free(tracker); - furi_message_queue_free(queue); - - furi_delay_ms(500); - - view_dispatcher_remove_view(view_dispatcher, 0); - tracker_view_free(tracker_view); - view_dispatcher_free(view_dispatcher); - - notification_message(notification, &sequence_display_backlight_enforce_auto); - - furi_record_close(RECORD_NOTIFICATION); - furi_record_close(RECORD_GUI); - - return 0; -} \ No newline at end of file diff --git a/applications/external/music_tracker/zero_tracker.h b/applications/external/music_tracker/zero_tracker.h deleted file mode 100644 index e69de29bb..000000000 diff --git a/applications/external/music_tracker/zero_tracker.png b/applications/external/music_tracker/zero_tracker.png deleted file mode 100644 index 61488d153..000000000 Binary files a/applications/external/music_tracker/zero_tracker.png and /dev/null differ diff --git a/applications/external/rubiks_cube_scrambler/LICENSE b/applications/external/rubiks_cube_scrambler/LICENSE deleted file mode 100644 index 4a6de25cb..000000000 --- a/applications/external/rubiks_cube_scrambler/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2022 RaZe - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/applications/external/rubiks_cube_scrambler/application.fam b/applications/external/rubiks_cube_scrambler/application.fam deleted file mode 100644 index 1d51ecdd5..000000000 --- a/applications/external/rubiks_cube_scrambler/application.fam +++ /dev/null @@ -1,24 +0,0 @@ -# COMPILE ISTRUCTIONS: - -# Clean the code and remove old binaries/compilation artefact -# ./fbt -c fap_rubiks_cube_scrambler - -# Compile FAP -# ./fbt fap_rubiks_cube_scrambler - -# Run application directly inside the Flip.x0 -# ./fbt launch_app APPSRC=rubiks_cube_scrambler - -App( - appid="rubiks_cube_scrambler", - name="Rubik's Cube Scrambler", - apptype=FlipperAppType.EXTERNAL, - entry_point="rubiks_cube_scrambler_main", - stack_size=1 * 1024, - fap_category="Games", - fap_icon="cube.png", - fap_author="@RaZeSloth", - fap_weburl="https://github.com/RaZeSloth/flipperzero-rubiks-cube-scrambler", - fap_version="1.1", - fap_description="App generates random moves to scramble a Rubik's cube.", -) diff --git a/applications/external/rubiks_cube_scrambler/cube.png b/applications/external/rubiks_cube_scrambler/cube.png deleted file mode 100644 index 3178a29d6..000000000 Binary files a/applications/external/rubiks_cube_scrambler/cube.png and /dev/null differ diff --git a/applications/external/rubiks_cube_scrambler/rubiks_cube_scrambler.c b/applications/external/rubiks_cube_scrambler/rubiks_cube_scrambler.c deleted file mode 100644 index 64031bfbe..000000000 --- a/applications/external/rubiks_cube_scrambler/rubiks_cube_scrambler.c +++ /dev/null @@ -1,113 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "scrambler.h" -#include "furi_hal_random.h" - -bool scrambleStarted = false; -char scramble_str[100] = {0}; -char scramble_start[100] = {0}; -char scramble_end[100] = {0}; -bool notifications_enabled = false; - -static void success_vibration() { - furi_hal_vibro_on(false); - furi_hal_vibro_on(true); - furi_delay_ms(50); - furi_hal_vibro_on(false); - return; -} -void split_array(char original[], int size, char first[], char second[]) { - int32_t mid = size / 2; - if(size % 2 != 0) { - mid++; - } - int32_t first_index = 0, second_index = 0; - for(int32_t i = 0; i < size; i++) { - if(i < mid) { - first[first_index++] = original[i]; - } else { - if(i == mid && (original[i] == '2' || original[i] == '\'')) { - continue; - } - second[second_index++] = original[i]; - } - } - first[first_index] = '\0'; - second[second_index] = '\0'; -} -void genScramble() { - scrambleReplace(); - strcpy(scramble_str, printData()); - split_array(scramble_str, strlen(scramble_str), scramble_start, scramble_end); -} - -static void draw_callback(Canvas* canvas, void* ctx) { - UNUSED(ctx); - canvas_clear(canvas); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 4, 13, "Rubik's Cube Scrambler"); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned(canvas, 64, 28, AlignCenter, AlignCenter, scramble_start); - canvas_draw_str_aligned(canvas, 64, 38, AlignCenter, AlignCenter, scramble_end); - elements_button_center(canvas, "New"); - - elements_button_left(canvas, notifications_enabled ? "On" : "Off"); -} - -static void input_callback(InputEvent* input_event, void* ctx) { - furi_assert(ctx); - FuriMessageQueue* event_queue = ctx; - furi_message_queue_put(event_queue, input_event, FuriWaitForever); -} - -int32_t rubiks_cube_scrambler_main(void* p) { - UNUSED(p); - InputEvent event; - - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); - - ViewPort* view_port = view_port_alloc(); - - view_port_draw_callback_set(view_port, draw_callback, NULL); - - view_port_input_callback_set(view_port, input_callback, event_queue); - - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - while(true) { - furi_check(furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk); - - if(event.key == InputKeyOk && event.type == InputTypeShort) { - genScramble(); - if(notifications_enabled) { - success_vibration(); - } - } - if(event.key == InputKeyLeft && event.type == InputTypeShort) { - if(notifications_enabled) { - notifications_enabled = false; - } else { - notifications_enabled = true; - success_vibration(); - } - } - if(event.key == InputKeyBack) { - break; - } - view_port_update(view_port); - } - - furi_message_queue_free(event_queue); - - gui_remove_view_port(gui, view_port); - - view_port_free(view_port); - furi_record_close(RECORD_GUI); - return 0; -} diff --git a/applications/external/rubiks_cube_scrambler/scrambler.c b/applications/external/rubiks_cube_scrambler/scrambler.c deleted file mode 100644 index b97a67400..000000000 --- a/applications/external/rubiks_cube_scrambler/scrambler.c +++ /dev/null @@ -1,60 +0,0 @@ -/* -Authors: Tanish Bhongade and RaZe -*/ - -#include -#include -#include -#include "furi_hal_random.h" -#include -#include -#include "scrambler.h" - -// 6 moves along with direction -char moves[6] = {'R', 'U', 'F', 'B', 'L', 'D'}; -char dir[4] = {'\'', '2'}; -const int32_t SLEN = 20; -#define RESULT_SIZE 100 - -struct GetScramble { - char mainScramble[25][3]; -}; -struct GetScramble a; - -void scrambleReplace() { - // Initialize the mainScramble array with all the possible moves - for(int32_t i = 0; i < SLEN; i++) { - a.mainScramble[i][0] = moves[furi_hal_random_get() % 6]; - a.mainScramble[i][1] = dir[furi_hal_random_get() % 3]; - } - - /* // Perform the Fisher-Yates shuffle - for (int32_t i = 6 - 1; i > 0; i--) - { - int32_t j = rand() % (i + 1); - char temp[3]; - strcpy(temp, a.mainScramble[i]); - strcpy(a.mainScramble[i], a.mainScramble[j]); - strcpy(a.mainScramble[j], temp); - } */ - - // Select the first 10 elements as the scramble, using only the first two elements of the dir array - for(int32_t i = 0; i < SLEN; i++) { - a.mainScramble[i][1] = dir[furi_hal_random_get() % 3]; - } - for(int32_t i = 1; i < SLEN; i++) { - while(a.mainScramble[i][0] == a.mainScramble[i - 2][0] || - a.mainScramble[i][0] == a.mainScramble[i - 1][0]) { - a.mainScramble[i][0] = moves[furi_hal_random_get() % 5]; - } - } -} - -char* printData() { - static char result[RESULT_SIZE]; - int32_t offset = 0; - for(int32_t loop = 0; loop < SLEN; loop++) { - offset += snprintf(result + offset, RESULT_SIZE - offset, "%s ", a.mainScramble[loop]); - } - return result; -} \ No newline at end of file diff --git a/applications/external/rubiks_cube_scrambler/scrambler.h b/applications/external/rubiks_cube_scrambler/scrambler.h deleted file mode 100644 index 557ef20ae..000000000 --- a/applications/external/rubiks_cube_scrambler/scrambler.h +++ /dev/null @@ -1,2 +0,0 @@ -void scrambleReplace(); -char* printData(); diff --git a/applications/external/snake_2/application.fam b/applications/external/snake_2/application.fam deleted file mode 100644 index f05f76441..000000000 --- a/applications/external/snake_2/application.fam +++ /dev/null @@ -1,15 +0,0 @@ -App( - appid="snake20", - name="Snake 2.0", - apptype=FlipperAppType.EXTERNAL, - entry_point="snake_20_app", - cdefines=["APP_SNAKE_20"], - requires=["gui"], - stack_size=1 * 1024, - fap_icon="snake_10px.png", - fap_category="Games", - fap_author="@Willzvul", - fap_weburl="https://github.com/Willzvul/Snake_2.0", - fap_version="2.0", - fap_description="Advanced Snake Game (Remake of original Snake)", -) diff --git a/applications/external/snake_2/snake_10px.png b/applications/external/snake_2/snake_10px.png deleted file mode 100644 index 125cfb334..000000000 Binary files a/applications/external/snake_2/snake_10px.png and /dev/null differ diff --git a/applications/external/snake_2/snake_20.c b/applications/external/snake_2/snake_20.c deleted file mode 100644 index c45c9796c..000000000 --- a/applications/external/snake_2/snake_20.c +++ /dev/null @@ -1,528 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -typedef struct { - // +-----x - // | - // | - // y - uint8_t x; - uint8_t y; -} Point; - -typedef enum { - GameStateLife, - GameStatePause, - // 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 15 * 31 //128 * 64 / 4 - -#define x_back_symbol 50 -#define y_back_symbol 9 - -typedef struct { - FuriMutex* mutex; - Point points[MAX_SNAKE_LEN]; - uint16_t len; - Direction currentMovement; - Direction nextMovement; // if backward of currentMovement, ignore - Point fruit; - GameState state; -} 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_vibro_on, - &message_note_c7, - &message_delay_50, - &message_sound_off, - &message_vibro_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); - - // Before the function is called, the state is set with the canvas_reset(canvas) - - // 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); - canvas_draw_dot(canvas, f.x + 3, f.y - 1); - canvas_draw_dot(canvas, f.x + 4, f.y - 2); - //canvas_draw_dot(canvas,f.x+4,f.y-3); - - // 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); - if(i == 0) { - canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, p.x + 1, p.y + 1, 2, 2); - canvas_set_color(canvas, ColorBlack); - } - } - - // Pause and GameOver banner - if(snake_state->state == GameStatePause || snake_state->state == GameStateGameOver) { - // Screen is 128x64 px - canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, 33, 19, 64, 26); - - canvas_set_color(canvas, ColorBlack); - canvas_draw_frame(canvas, 34, 20, 62, 24); - - canvas_set_font(canvas, FontPrimary); - if(snake_state->state == GameStateGameOver) { - canvas_draw_str_aligned(canvas, 65, 31, AlignCenter, AlignBottom, "Game Over"); - } - if(snake_state->state == GameStatePause) { - canvas_draw_str_aligned(canvas, 65, 31, AlignCenter, AlignBottom, "Pause"); - } - - canvas_set_font(canvas, FontSecondary); - char buffer[20]; - snprintf(buffer, sizeof(buffer), "Score: %u", snake_state->len - 7U); - canvas_draw_str_aligned(canvas, 65, 41, AlignCenter, AlignBottom, buffer); - - // Painting "back"-symbol, Help message for Exit App, ProgressBar - canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, 25, 2, 81, 11); - canvas_draw_box(canvas, 28, 54, 73, 9); - canvas_set_color(canvas, ColorBlack); - canvas_draw_str_aligned( - canvas, 65, 10, AlignCenter, AlignBottom, "Hold to Exit App"); - snprintf( - buffer, sizeof(buffer), "Complete: %-5.1f%%", (double)((snake_state->len - 7U) / 4.58)); - canvas_draw_str_aligned(canvas, 65, 62, AlignCenter, AlignBottom, buffer); - { - canvas_draw_dot(canvas, x_back_symbol + 0, y_back_symbol); - canvas_draw_dot(canvas, x_back_symbol + 1, y_back_symbol); - canvas_draw_dot(canvas, x_back_symbol + 2, y_back_symbol); - canvas_draw_dot(canvas, x_back_symbol + 3, y_back_symbol); - canvas_draw_dot(canvas, x_back_symbol + 4, y_back_symbol); - canvas_draw_dot(canvas, x_back_symbol + 5, y_back_symbol - 1); - canvas_draw_dot(canvas, x_back_symbol + 6, y_back_symbol - 2); - canvas_draw_dot(canvas, x_back_symbol + 6, y_back_symbol - 3); - canvas_draw_dot(canvas, x_back_symbol + 5, y_back_symbol - 4); - canvas_draw_dot(canvas, x_back_symbol + 4, y_back_symbol - 5); - canvas_draw_dot(canvas, x_back_symbol + 3, y_back_symbol - 5); - canvas_draw_dot(canvas, x_back_symbol + 2, y_back_symbol - 5); - canvas_draw_dot(canvas, x_back_symbol + 1, y_back_symbol - 5); - canvas_draw_dot(canvas, x_back_symbol + 0, y_back_symbol - 5); - canvas_draw_dot(canvas, x_back_symbol - 1, y_back_symbol - 5); - canvas_draw_dot(canvas, x_back_symbol - 2, y_back_symbol - 5); - canvas_draw_dot(canvas, x_back_symbol - 3, y_back_symbol - 5); - canvas_draw_dot(canvas, x_back_symbol - 2, y_back_symbol - 6); - canvas_draw_dot(canvas, x_back_symbol - 2, y_back_symbol - 4); - canvas_draw_dot(canvas, x_back_symbol - 1, y_back_symbol - 6); - canvas_draw_dot(canvas, x_back_symbol - 1, y_back_symbol - 4); - canvas_draw_dot(canvas, x_back_symbol - 1, y_back_symbol - 7); - canvas_draw_dot(canvas, x_back_symbol - 1, y_back_symbol - 3); - } - } - - 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; - } - - 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) { - //You win!!! - 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); - notification_message(notification, &sequence_blink_red_100); - } -} - -int32_t snake_20_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"); - furi_message_queue_free(event_queue); - 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) { - if(event.type == EventTypeKey) { - // press events - if(event.input.type == InputTypePress) { - switch(event.input.key) { - case InputKeyUp: - if(snake_state->state != GameStatePause) { - snake_state->nextMovement = DirectionUp; - } - break; - case InputKeyDown: - if(snake_state->state != GameStatePause) { - snake_state->nextMovement = DirectionDown; - } - break; - case InputKeyRight: - if(snake_state->state != GameStatePause) { - snake_state->nextMovement = DirectionRight; - } - break; - case InputKeyLeft: - if(snake_state->state != GameStatePause) { - snake_state->nextMovement = DirectionLeft; - } - break; - case InputKeyOk: - if(snake_state->state == GameStateGameOver) { - snake_game_init_game(snake_state); - } - if(snake_state->state == GameStatePause) { - furi_timer_start(timer, furi_kernel_get_tick_frequency() / 4); - snake_state->state = GameStateLife; - } - break; - case InputKeyBack: - if(snake_state->state == GameStateLife) { - furi_timer_stop(timer); - snake_state->state = GameStatePause; - break; - } - if(snake_state->state == GameStatePause) { - furi_timer_start(timer, furi_kernel_get_tick_frequency() / 4); - snake_state->state = GameStateLife; - break; - } - if(snake_state->state == GameStateGameOver) { - snake_game_init_game(snake_state); - } - default: - break; - } - } - //LongPress Events - if(event.input.type == InputTypeLong) { - switch(event.input.key) { - case InputKeyUp: - if(snake_state->state != GameStatePause) { - snake_state->nextMovement = DirectionUp; - furi_timer_start(timer, furi_kernel_get_tick_frequency() / 8); - } - break; - case InputKeyDown: - if(snake_state->state != GameStatePause) { - snake_state->nextMovement = DirectionDown; - furi_timer_start(timer, furi_kernel_get_tick_frequency() / 8); - } - break; - case InputKeyRight: - if(snake_state->state != GameStatePause) { - snake_state->nextMovement = DirectionRight; - furi_timer_start(timer, furi_kernel_get_tick_frequency() / 8); - } - break; - case InputKeyLeft: - if(snake_state->state != GameStatePause) { - snake_state->nextMovement = DirectionLeft; - furi_timer_start(timer, furi_kernel_get_tick_frequency() / 8); - } - break; - case InputKeyBack: - processing = false; - break; - default: - break; - } - } - //ReleaseKey Event - if(event.input.type == InputTypeRelease) { - if(snake_state->state != GameStatePause) { - furi_timer_start(timer, furi_kernel_get_tick_frequency() / 4); - } - } - } 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); - } - - // Wait for all notifications to be played and return backlight to normal state - notification_message_block(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; -} \ No newline at end of file diff --git a/applications/external/tama_p1/application.fam b/applications/external/tama_p1/application.fam deleted file mode 100644 index 4152b054c..000000000 --- a/applications/external/tama_p1/application.fam +++ /dev/null @@ -1,11 +0,0 @@ -App( - appid="tama_p1", - name="Tamagotchi", - apptype=FlipperAppType.EXTERNAL, - entry_point="tama_p1_app", - cdefines=["APP_TAMA_P1"], - requires=["gui", "storage"], - stack_size=2 * 1024, - fap_icon="tamaIcon.png", - fap_category="Games", -) diff --git a/applications/external/tama_p1/compiled/assets_icons.h b/applications/external/tama_p1/compiled/assets_icons.h deleted file mode 100644 index aa2735b72..000000000 --- a/applications/external/tama_p1/compiled/assets_icons.h +++ /dev/null @@ -1,66 +0,0 @@ -#include - -const uint8_t _I_icon_0_0[] = { - 0x01, 0x00, 0x1a, 0x00, 0x00, 0x0d, 0xaa, 0x1d, 0x7e, 0x00, 0x9c, 0x3e, 0xf9, 0x0f, 0x9e, - 0x43, 0xe3, 0x00, 0x12, 0x9c, 0x43, 0xa7, 0x10, 0xc9, 0xe4, 0x30, 0x0a, 0x31, 0x08, 0x60, -}; -const uint8_t* const _I_icon_0[] = {_I_icon_0_0}; - -const uint8_t _I_icon_1_0[] = { - 0x00, 0x00, 0x00, 0x40, 0x04, 0x04, 0x04, 0xf0, 0x11, 0xf9, 0x1b, 0xf8, 0x07, 0x8c, 0x06, - 0xed, 0x36, 0xac, 0x26, 0xe8, 0x02, 0x52, 0x0b, 0x02, 0x18, 0xe0, 0x01, 0xe0, 0x01, -}; -const uint8_t* const _I_icon_1[] = {_I_icon_1_0}; - -const uint8_t _I_icon_2_0[] = { - 0x00, 0x00, 0x00, 0x0e, 0x00, 0x13, 0x00, 0x21, 0x3c, 0x21, 0x3e, 0x23, 0x3f, 0x9f, 0x1f, - 0xc0, 0x0f, 0xe0, 0x07, 0xf0, 0x01, 0x7c, 0x00, 0x1f, 0x00, 0x06, 0x00, 0x06, 0x00, -}; -const uint8_t* const _I_icon_2[] = {_I_icon_2_0}; - -const uint8_t _I_icon_3_0[] = { - 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x1c, 0x40, 0x3a, 0xc0, 0x36, 0xf0, 0x37, 0x18, 0x2d, - 0x0c, 0x2b, 0x0e, 0x02, 0x1f, 0x06, 0x3e, 0x07, 0xfe, 0x00, 0x7f, 0x00, 0x18, 0x00, -}; -const uint8_t* const _I_icon_3[] = {_I_icon_3_0}; - -const uint8_t _I_icon_4_0[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0xc7, 0x3c, 0x82, 0x2f, 0xf2, 0x26, 0xc7, 0x2c, - 0x69, 0x28, 0x2f, 0x2c, 0xe7, 0x27, 0x02, 0x20, 0x02, 0x30, 0x06, 0x1c, 0xfc, 0x0f, -}; -const uint8_t* const _I_icon_4[] = {_I_icon_4_0}; - -const uint8_t _I_icon_5_0[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0xfe, 0x0f, 0x03, 0x38, 0xc9, 0x22, 0x9a, 0x32, - 0xa2, 0x28, 0x24, 0x2c, 0x21, 0x20, 0x61, 0x30, 0x21, 0x10, 0xf3, 0x11, 0x1e, 0x0f, -}; -const uint8_t* const _I_icon_5[] = {_I_icon_5_0}; - -const uint8_t _I_icon_6_0[] = { - 0x01, 0x00, 0x17, 0x00, 0x00, 0x44, 0x62, 0xfd, 0x38, 0xbf, 0xcf, 0xb7, 0xf3, 0xf8, - 0xfc, 0x6e, 0x3f, 0x1a, 0xff, 0xc0, 0x3f, 0xf0, 0x1f, 0xf4, 0x02, 0x71, 0x00, -}; -const uint8_t* const _I_icon_6[] = {_I_icon_6_0}; - -const uint8_t _I_icon_7_0[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x41, 0x0e, 0xc4, 0x1f, 0x94, 0x20, - 0x00, 0x21, 0x22, 0x1f, 0x1d, 0x0a, 0x63, 0x20, 0xde, 0x20, 0x80, 0x1f, 0x00, 0x0e, -}; -const uint8_t* const _I_icon_7[] = {_I_icon_7_0}; - -const Icon I_icon_0 = - {.width = 14, .height = 14, .frame_count = 1, .frame_rate = 0, .frames = _I_icon_0}; -const Icon I_icon_1 = - {.width = 14, .height = 14, .frame_count = 1, .frame_rate = 0, .frames = _I_icon_1}; -const Icon I_icon_2 = - {.width = 14, .height = 14, .frame_count = 1, .frame_rate = 0, .frames = _I_icon_2}; -const Icon I_icon_3 = - {.width = 14, .height = 14, .frame_count = 1, .frame_rate = 0, .frames = _I_icon_3}; -const Icon I_icon_4 = - {.width = 14, .height = 14, .frame_count = 1, .frame_rate = 0, .frames = _I_icon_4}; -const Icon I_icon_5 = - {.width = 14, .height = 14, .frame_count = 1, .frame_rate = 0, .frames = _I_icon_5}; -const Icon I_icon_6 = - {.width = 14, .height = 14, .frame_count = 1, .frame_rate = 0, .frames = _I_icon_6}; -const Icon I_icon_7 = - {.width = 14, .height = 14, .frame_count = 1, .frame_rate = 0, .frames = _I_icon_7}; \ No newline at end of file diff --git a/applications/external/tama_p1/hal.c b/applications/external/tama_p1/hal.c deleted file mode 100644 index 585cd88c4..000000000 --- a/applications/external/tama_p1/hal.c +++ /dev/null @@ -1,146 +0,0 @@ -#include -#include -#include -#include -#include "tama.h" - -#define TAG_HAL "TamaLIB" - -static void* tama_p1_hal_malloc(u32_t size) { - return malloc(size); -} - -static void tama_p1_hal_free(void* ptr) { - free(ptr); -} - -static void tama_p1_hal_halt(void) { - g_ctx->halted = true; -} - -static bool_t tama_p1_hal_is_log_enabled(log_level_t level) { - switch(level) { - case LOG_ERROR: - return true; - case LOG_INFO: - return true; - case LOG_MEMORY: - return false; - case LOG_CPU: - return false; - default: - return false; - } -} - -static void tama_p1_hal_log(log_level_t level, char* buff, ...) { - if(!tama_p1_hal_is_log_enabled(level)) return; - - FuriString* string = furi_string_alloc(); - va_list args; - va_start(args, buff); - furi_string_cat_vprintf(string, buff, args); - va_end(args); - - switch(level) { - case LOG_ERROR: - FURI_LOG_E(TAG_HAL, "%s", furi_string_get_cstr(string)); - break; - case LOG_INFO: - FURI_LOG_I(TAG_HAL, "%s", furi_string_get_cstr(string)); - break; - case LOG_MEMORY: - break; - case LOG_CPU: - FURI_LOG_D(TAG_HAL, "%s", furi_string_get_cstr(string)); - break; - default: - FURI_LOG_D(TAG_HAL, "%s", furi_string_get_cstr(string)); - break; - } - - furi_string_free(string); -} - -static void tama_p1_hal_sleep_until(timestamp_t ts) { - while(true) { - uint32_t count = LL_TIM_GetCounter(TIM2); - uint32_t delay = ts - count; - // FURI_LOG_D(TAG, "delay: %x", delay); - // Stolen from furi_delay_until_tick - if(delay != 0 && 0 == (delay >> (8 * sizeof(uint32_t) - 1))) { - // Not the best place to release mutex, but this is the only place we know whether - // we're ahead or behind, otherwise around the step call we'll always have to - // delay a tick and run more and more behind. - furi_mutex_release(g_state_mutex); - furi_delay_tick(1); - while(furi_mutex_acquire(g_state_mutex, FuriWaitForever) != FuriStatusOk) - furi_delay_tick(1); - } else { - break; - } - } -} - -static timestamp_t tama_p1_hal_get_timestamp(void) { - return LL_TIM_GetCounter(TIM2); -} - -static void tama_p1_hal_update_screen(void) { - // Do nothing, covered by main loop -} - -static void tama_p1_hal_set_lcd_matrix(u8_t x, u8_t y, bool_t val) { - if(val) - g_ctx->framebuffer[y] |= 1 << x; - else - g_ctx->framebuffer[y] &= ~(1 << x); -} - -static void tama_p1_hal_set_lcd_icon(u8_t icon, bool_t val) { - if(val) - g_ctx->icons |= 1 << icon; - else - g_ctx->icons &= ~(1 << icon); -} - -static void tama_p1_hal_play_frequency(bool_t en) { - if(en) { - if(furi_hal_speaker_is_mine() || furi_hal_speaker_acquire(30)) { - furi_hal_speaker_start(g_ctx->frequency, 0.5f); - } - } else { - if(furi_hal_speaker_is_mine()) { - furi_hal_speaker_stop(); - furi_hal_speaker_release(); - } - } - - g_ctx->buzzer_on = en; -} - -static void tama_p1_hal_set_frequency(u32_t freq) { - g_ctx->frequency = freq / 10.0F; - if(g_ctx->buzzer_on) tama_p1_hal_play_frequency(true); -} - -static int tama_p1_hal_handler(void) { - // Do nothing - return 0; -} - -void tama_p1_hal_init(hal_t* hal) { - hal->malloc = tama_p1_hal_malloc; - hal->free = tama_p1_hal_free; - hal->halt = tama_p1_hal_halt; - hal->is_log_enabled = tama_p1_hal_is_log_enabled; - hal->log = tama_p1_hal_log; - hal->sleep_until = tama_p1_hal_sleep_until; - hal->get_timestamp = tama_p1_hal_get_timestamp; - hal->update_screen = tama_p1_hal_update_screen; - hal->set_lcd_matrix = tama_p1_hal_set_lcd_matrix; - hal->set_lcd_icon = tama_p1_hal_set_lcd_icon; - hal->set_frequency = tama_p1_hal_set_frequency; - hal->play_frequency = tama_p1_hal_play_frequency; - hal->handler = tama_p1_hal_handler; -} \ No newline at end of file diff --git a/applications/external/tama_p1/hal_types.h b/applications/external/tama_p1/hal_types.h deleted file mode 100644 index d27e6dfbe..000000000 --- a/applications/external/tama_p1/hal_types.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * TamaLIB - A hardware agnostic tama P1 emulation library - * - * Copyright (C) 2021 Jean-Christophe Rona - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#ifndef _HAL_TYPES_H_ -#define _HAL_TYPES_H_ - -#include - -typedef bool bool_t; -typedef uint8_t u4_t; -typedef uint8_t u5_t; -typedef uint8_t u8_t; -typedef uint16_t u12_t; -typedef uint16_t u13_t; -typedef uint32_t u32_t; -typedef uint32_t - timestamp_t; // WARNING: Must be an unsigned type to properly handle wrapping (u32 wraps in around 1h11m when expressed in us) - -#endif /* _HAL_TYPES_H_ */ diff --git a/applications/external/tama_p1/icons/icon_0.png b/applications/external/tama_p1/icons/icon_0.png deleted file mode 100644 index 7b94d3511..000000000 Binary files a/applications/external/tama_p1/icons/icon_0.png and /dev/null differ diff --git a/applications/external/tama_p1/icons/icon_1.png b/applications/external/tama_p1/icons/icon_1.png deleted file mode 100644 index 934cf7187..000000000 Binary files a/applications/external/tama_p1/icons/icon_1.png and /dev/null differ diff --git a/applications/external/tama_p1/icons/icon_2.png b/applications/external/tama_p1/icons/icon_2.png deleted file mode 100644 index b83e449d9..000000000 Binary files a/applications/external/tama_p1/icons/icon_2.png and /dev/null differ diff --git a/applications/external/tama_p1/icons/icon_3.png b/applications/external/tama_p1/icons/icon_3.png deleted file mode 100644 index 34f4db24d..000000000 Binary files a/applications/external/tama_p1/icons/icon_3.png and /dev/null differ diff --git a/applications/external/tama_p1/icons/icon_4.png b/applications/external/tama_p1/icons/icon_4.png deleted file mode 100644 index fe02b83af..000000000 Binary files a/applications/external/tama_p1/icons/icon_4.png and /dev/null differ diff --git a/applications/external/tama_p1/icons/icon_5.png b/applications/external/tama_p1/icons/icon_5.png deleted file mode 100644 index 889acd50e..000000000 Binary files a/applications/external/tama_p1/icons/icon_5.png and /dev/null differ diff --git a/applications/external/tama_p1/icons/icon_6.png b/applications/external/tama_p1/icons/icon_6.png deleted file mode 100644 index 57d2f181b..000000000 Binary files a/applications/external/tama_p1/icons/icon_6.png and /dev/null differ diff --git a/applications/external/tama_p1/icons/icon_7.png b/applications/external/tama_p1/icons/icon_7.png deleted file mode 100644 index 4ff6e504a..000000000 Binary files a/applications/external/tama_p1/icons/icon_7.png and /dev/null differ diff --git a/applications/external/tama_p1/tama.h b/applications/external/tama_p1/tama.h deleted file mode 100644 index 7cbcbcfb1..000000000 --- a/applications/external/tama_p1/tama.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include -#include "tamalib/tamalib.h" - -#define TAG "TamaP1" -#define TAMA_ROM_PATH APP_DATA_PATH("rom.bin") -#define TAMA_SCREEN_SCALE_FACTOR 2 -#define TAMA_LCD_ICON_SIZE 14 -#define TAMA_LCD_ICON_MARGIN 1 - -#define STATE_FILE_MAGIC "TLST" -#define STATE_FILE_VERSION 2 -#define TAMA_SAVE_PATH APP_DATA_PATH("save.bin") - -typedef struct { - FuriThread* thread; - hal_t hal; - uint8_t* rom; - // 32x16 screen, perfectly represented through uint32_t - uint32_t framebuffer[16]; - uint8_t icons; - bool halted; - bool fast_forward_done; - bool buzzer_on; - float frequency; -} TamaApp; - -typedef enum { - EventTypeInput, - EventTypeTick, -} EventType; - -typedef struct { - EventType type; - InputEvent input; -} TamaEvent; - -extern TamaApp* g_ctx; -extern FuriMutex* g_state_mutex; - -void tama_p1_hal_init(hal_t* hal); diff --git a/applications/external/tama_p1/tamaIcon.png b/applications/external/tama_p1/tamaIcon.png deleted file mode 100644 index ccdf23972..000000000 Binary files a/applications/external/tama_p1/tamaIcon.png and /dev/null differ diff --git a/applications/external/tama_p1/tama_p1.c b/applications/external/tama_p1/tama_p1.c deleted file mode 100644 index 476665059..000000000 --- a/applications/external/tama_p1/tama_p1.c +++ /dev/null @@ -1,1193 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "tamalib/tamalib.h" -#include "tama.h" -#include "compiled/assets_icons.h" -#include - -TamaApp* g_ctx; -FuriMutex* g_state_mutex; -uint8_t layout_mode = 0; // 3: portrait => 4: portrait <= -// 0: landscape (small) 1: landscape (big) 2: landscape (full) -bool in_menu = false; - -uint8_t speed = 1; -const uint8_t speed_options[] = {1, 2, 4}; -const uint8_t min_speed = 1; -const uint8_t max_speed = 4; -const uint8_t speed_options_size = 3; -// = sizeof(speed_options) / sizeof(speed_options[0]); - -uint8_t menu_cursor = 3; // 0: layout mode; 1: speed; 2: A+C; -const uint8_t menu_items = 4; // 3: Close menu, Save & Exit -uint8_t sub_menu_buttons = 0; -uint8_t sub_menu_last = 0; - -static const Icon* icons_list[] = { - &I_icon_0, - &I_icon_1, - &I_icon_2, - &I_icon_3, - &I_icon_4, - &I_icon_5, - &I_icon_6, - &I_icon_7, -}; - -static InputKey m = InputKeyUp; -static InputKey a = InputKeyLeft; -static InputKey b = InputKeyDown; -static InputKey c = InputKeyRight; - -static void speed_up() { - switch(speed) { - case max_speed: - speed = speed_options[0]; - break; - default: - for(uint8_t i = 0; i < speed_options_size - 1; i++) { - if(speed == speed_options[i]) { - speed = speed_options[i + 1]; - break; - } - } - break; - } - tamalib_set_speed(speed); -} -static void speed_down() { - switch(speed) { - case min_speed: - speed = speed_options[speed_options_size - 1]; - break; - default: - for(uint8_t i = speed_options_size - 1; i > 0; i--) { - if(speed == speed_options[i]) { - speed = speed_options[i - 1]; - break; - } - } - break; - } - tamalib_set_speed(speed); -} - -// static void draw_landscape(Canvas* const canvas, void* cb_ctx) -static void draw_landscape(Canvas* const canvas, uint8_t scale) { - // FURI_LOG_D(TAG, "Drawing frame"); - // Calculate positioning - uint16_t canv_width = canvas_width(canvas); - uint16_t canv_height = canvas_height(canvas); - uint16_t lcd_matrix_scaled_width = 32 * scale; - uint16_t lcd_matrix_scaled_height = 16 * scale; - uint16_t lcd_matrix_top = (canv_height - lcd_matrix_scaled_height) / 2; // 0 - uint16_t lcd_matrix_left = (canv_width - lcd_matrix_scaled_width) / 2; - - // uint16_t lcd_icon_upper_top = lcd_matrix_top - TAMA_LCD_ICON_SIZE - TAMA_LCD_ICON_MARGIN; - // uint16_t lcd_icon_lower_top = lcd_matrix_top + lcd_matrix_scaled_height + TAMA_LCD_ICON_MARGIN; - uint16_t lcd_icon_upper_left = lcd_matrix_left; - uint16_t lcd_icon_lower_left = lcd_matrix_left; - uint16_t lcd_icon_spacing_horiz = - (lcd_matrix_scaled_width - (4 * TAMA_LCD_ICON_SIZE)) / 3 + TAMA_LCD_ICON_SIZE; - - uint16_t y = lcd_matrix_top; - for(uint8_t row = 0; row < 16; ++row) { - uint16_t x = lcd_matrix_left; - uint32_t row_pixels = g_ctx->framebuffer[row]; - for(uint8_t col = 0; col < 32; ++col) { - if(row_pixels & 1) { - canvas_draw_box(canvas, x, y, scale, scale); - } - x += scale; - row_pixels >>= 1; - } - y += scale; - } - - // Start drawing icons - uint8_t lcd_icons = g_ctx->icons; - - // Draw top icons - y = 0; - uint16_t x_ic = lcd_icon_upper_left; - for(uint8_t i = 0; i < 4; ++i) { - if(lcd_icons & 1) { - canvas_draw_icon(canvas, x_ic, y, icons_list[i]); - } - // x_ic += TAMA_LCD_ICON_SIZE + 4; - // if(scale == 3) { - // y += 16; - // } else { - x_ic += lcd_icon_spacing_horiz; - // } - lcd_icons >>= 1; - } - - // Draw bottom icons - y = 64 - TAMA_LCD_ICON_SIZE; - // if(scale == 3) { - // y = 0; - // x_ic = 128 - TAMA_LCD_ICON_SIZE; - // x_ic = 0; - // } else { - // y = 64 - TAMA_LCD_ICON_SIZE; - x_ic = lcd_icon_lower_left; - // } - for(uint8_t i = 4; i < 8; ++i) { - // canvas_draw_frame(canvas, x_ic, y, TAMA_LCD_ICON_SIZE, TAMA_LCD_ICON_SIZE); - if(lcd_icons & 1) { - canvas_draw_icon(canvas, x_ic, y, icons_list[i]); - } - // if(scale == 3) { - // y += 16; - // } else { - x_ic += lcd_icon_spacing_horiz; - // } - lcd_icons >>= 1; - } -} -// static void draw_portrait_right(Canvas* const canvas, void* cb_ctx) -static void draw_portrait_right(Canvas* const canvas, uint8_t scale) { - // FURI_LOG_D(TAG, "Drawing frame"); - // Calculate positioning - // uint16_t canv_width = canvas_width(canvas); - uint16_t canv_height = canvas_height(canvas); - uint16_t lcd_matrix_scaled_width = 32 * scale; - uint16_t lcd_matrix_scaled_height = 16 * scale; - // uint16_t lcd_matrix_top = 0; - uint16_t lcd_matrix_top = (canv_height - lcd_matrix_scaled_height) / 2; - // uint16_t lcd_matrix_left = (canv_width - lcd_matrix_scaled_width) / 2; - uint16_t lcd_matrix_left = 64 - TAMA_LCD_ICON_SIZE; - uint16_t lcd_icon_upper_left = lcd_matrix_left; - uint16_t lcd_icon_lower_left = lcd_matrix_left; - uint16_t lcd_icon_spacing_horiz = - (lcd_matrix_scaled_width - (4 * TAMA_LCD_ICON_SIZE)) / 3 + TAMA_LCD_ICON_SIZE; - - uint16_t y = lcd_matrix_top; // 64 - for(uint8_t row = 0; row < 16; ++row) { - uint16_t x = 128; // lcd_matrix_left - uint32_t row_pixels = g_ctx->framebuffer[row]; - for(uint8_t col = 0; col < 32; ++col) { - if(row_pixels & 1) { - canvas_draw_box(canvas, y + 32, x - 66, scale, scale); - } - x -= scale; - row_pixels >>= 1; - } - y += scale; - } - - // Start drawing icons - uint8_t lcd_icons = g_ctx->icons; - - // Draw top icons - // y = lcd_icon_upper_top; - y = 30; - // y = 64 - TAMA_LCD_ICON_SIZE; - uint16_t x_ic = lcd_icon_upper_left; - // uint16_t x_ic = 64 - TAMA_LCD_ICON_SIZE; - for(uint8_t i = 0; i < 4; ++i) { - if(lcd_icons & 1) { - canvas_draw_icon(canvas, y, x_ic, icons_list[i]); - } - x_ic -= lcd_icon_spacing_horiz; // TAMA_LCD_ICON_SIZE + 4; - lcd_icons >>= 1; - } - - // Draw bottom icons - y = 84; // lcd_icon_lower_top - x_ic = lcd_icon_lower_left; // 64 - TAMA_LCD_ICON_SIZE - for(uint8_t i = 4; i < 8; ++i) { - // canvas_draw_frame(canvas, x_ic, y, TAMA_LCD_ICON_SIZE, TAMA_LCD_ICON_SIZE); - if(lcd_icons & 1) { - canvas_draw_icon(canvas, y, x_ic, icons_list[i]); - } - x_ic -= lcd_icon_spacing_horiz; - lcd_icons >>= 1; - } -} -static void draw_portrait_left(Canvas* const canvas, uint8_t scale) { - // FURI_LOG_D(TAG, "Drawing frame"); - // Calculate positioning - // uint16_t canv_width = canvas_width(canvas); - // uint16_t canv_height = canvas_height(canvas); - uint16_t lcd_matrix_scaled_width = 32 * scale; - // uint16_t lcd_matrix_scaled_height = 16 * scale; - // uint16_t lcd_matrix_top = 0; - // uint16_t lcd_matrix_top = (canv_height - lcd_matrix_scaled_height) / 2; - // uint16_t lcd_matrix_left = (canv_width - lcd_matrix_scaled_width) / 2; - uint16_t lcd_matrix_left = 0; - uint16_t lcd_icon_upper_left = lcd_matrix_left; - uint16_t lcd_icon_lower_left = lcd_matrix_left; - uint16_t lcd_icon_spacing_horiz = - (lcd_matrix_scaled_width - (4 * TAMA_LCD_ICON_SIZE)) / 3 + TAMA_LCD_ICON_SIZE; - - // uint16_t y = 64 + lcd_matrix_top; - uint16_t y = 64; - for(uint8_t row = 0; row < 16; ++row) { - uint16_t x = 0; // lcd_matrix_left - uint32_t row_pixels = g_ctx->framebuffer[row]; - for(uint8_t col = 0; col < 32; ++col) { - if(row_pixels & 1) { - canvas_draw_box(canvas, y, x, scale, scale); - } - x += scale; - row_pixels >>= 1; - } - y -= scale; - } - - // Start drawing icons - uint8_t lcd_icons = g_ctx->icons; - - // Draw top icons - // y = lcd_icon_upper_top; - y = 70; - // y = 64 - TAMA_LCD_ICON_SIZE; - uint16_t x_ic = lcd_icon_upper_left; - // uint16_t x_ic = 64 - TAMA_LCD_ICON_SIZE; - for(uint8_t i = 0; i < 4; ++i) { - if(lcd_icons & 1) { - canvas_draw_icon(canvas, y, x_ic, icons_list[i]); - } - x_ic += lcd_icon_spacing_horiz; // TAMA_LCD_ICON_SIZE + 4; - lcd_icons >>= 1; - } - - // Draw bottom icons - y = 16; // lcd_icon_lower_top - x_ic = lcd_icon_lower_left; // 64 - TAMA_LCD_ICON_SIZE - for(uint8_t i = 4; i < 8; ++i) { - // canvas_draw_frame(canvas, x_ic, y, TAMA_LCD_ICON_SIZE, TAMA_LCD_ICON_SIZE); - if(lcd_icons & 1) { - canvas_draw_icon(canvas, y, x_ic, icons_list[i]); - } - x_ic += lcd_icon_spacing_horiz; - lcd_icons >>= 1; - } -} -// static void draw_mini(Canvas* const canvas, uint16_t inX, uint16_t inY) -static void draw_mini(Canvas* const canvas) { - // Calculate positioning - // uint16_t y = inY; - const uint16_t y = 34; - const uint16_t x = 84; - - uint16_t y1 = y; - for(uint8_t row = 0; row < 16; ++row) { - // uint16_t x = inX; - uint16_t x1 = x; - uint32_t row_pixels = g_ctx->framebuffer[row]; - for(uint8_t col = 0; col < 32; ++col) { - if(row_pixels & 1) { - canvas_draw_dot(canvas, x1, y1); - } - x1 += 1; - row_pixels >>= 1; - } - y1 += 1; - } - - // Start drawing icons - uint8_t lcd_icons = g_ctx->icons; - - // Draw top icons - uint16_t y2 = y - 2; - uint16_t x_ic = x; - for(uint8_t i = 0; i < 4; ++i) { - if(lcd_icons & 1) { - // canvas_draw_icon(canvas, x_ic, y, icons_list[i]); - canvas_draw_line(canvas, x_ic, y2, x_ic + 6, y2); - } - x_ic += 8; - lcd_icons >>= 1; - } - - // Draw bottom icons - y2 = y + 17; - x_ic = x; - for(uint8_t i = 4; i < 8; ++i) { - // canvas_draw_frame(canvas, x_ic, y, TAMA_LCD_ICON_SIZE, TAMA_LCD_ICON_SIZE); - if(lcd_icons & 1) { - // canvas_draw_icon(canvas, x_ic, y, icons_list[i]); - canvas_draw_line(canvas, x_ic, y2, x_ic + 6, y2); - } - x_ic += 8; - lcd_icons >>= 1; - } -} - -static void draw_menu(Canvas* const canvas) { - canvas_draw_frame(canvas, 0, 0, 128, 64); - canvas_draw_str_aligned(canvas, 64, 6, AlignCenter, AlignCenter, "Menu"); - canvas_draw_line(canvas, 0, 10, 128, 10); - draw_mini(canvas); - // draw_mini(canvas, 34, 84); - - switch(menu_cursor) { - case 0: - canvas_draw_triangle(canvas, 4, 16, 6, 6, CanvasDirectionLeftToRight); - break; - case 1: - canvas_draw_triangle(canvas, 4, 26, 6, 6, CanvasDirectionLeftToRight); - break; - case 2: - switch(sub_menu_buttons) { - case 0: - canvas_draw_triangle(canvas, 4, 36, 6, 6, CanvasDirectionLeftToRight); - break; - case 1: - canvas_draw_triangle(canvas, 47, 44, 6, 4, CanvasDirectionBottomToTop); - break; - case 2: - canvas_draw_triangle(canvas, 57, 44, 6, 4, CanvasDirectionBottomToTop); - break; - case 3: - canvas_draw_triangle(canvas, 67, 44, 6, 4, CanvasDirectionBottomToTop); - break; - default: - break; - } - break; - case menu_items - 1: - switch(sub_menu_last) { - case 0: - canvas_draw_triangle(canvas, 4, 56, 6, 6, CanvasDirectionLeftToRight); - break; - case 1: - canvas_draw_triangle(canvas, 36, 56, 6, 6, CanvasDirectionLeftToRight); - break; - case 2: - canvas_draw_triangle(canvas, 67, 56, 6, 6, CanvasDirectionLeftToRight); - break; - default: - break; - } - break; - } - switch(layout_mode) { - case 0: - canvas_draw_str(canvas, 12, 20, "Layout: Landscape (small)"); - break; - case 1: - canvas_draw_str(canvas, 12, 20, "Layout: Landscape (big)"); - break; - case 2: - canvas_draw_str(canvas, 12, 20, "Layout: Landscape (full)"); - break; - case 3: - canvas_draw_str(canvas, 12, 20, "Layout: Portrait =>"); - break; - case 4: - canvas_draw_str(canvas, 12, 20, "Layout: Portrait <="); - break; - default: - canvas_draw_str(canvas, 12, 20, "Layout: ???"); - break; - } - switch(speed) { // match with speed_options - // case 0: // freeze menu too - // canvas_draw_str(canvas, 12, 30, "Speed: 0x"); - // break; - case 1: - canvas_draw_str(canvas, 12, 30, "Speed: 1x"); - break; - case 2: - canvas_draw_str(canvas, 12, 30, "Speed: 2x"); - break; - case 4: - canvas_draw_str(canvas, 12, 30, "Speed: 4x (max)"); - break; - default: - canvas_draw_str(canvas, 12, 30, "Speed ??x"); - break; - } - canvas_draw_str(canvas, 12, 40, "A+C"); - canvas_draw_str(canvas, 45, 40, "A"); - canvas_draw_str(canvas, 55, 40, "B"); - canvas_draw_str(canvas, 65, 40, "C"); - - canvas_draw_str(canvas, 12, 60, "Close"); - canvas_draw_str(canvas, 44, 60, "Save"); - canvas_draw_str(canvas, 75, 60, "Save & Exit"); -} - -static void tama_p1_draw_callback(Canvas* const canvas, void* cb_ctx) { - furi_assert(cb_ctx); - - FuriMutex* const mutex = cb_ctx; - if(furi_mutex_acquire(mutex, 25) != FuriStatusOk) return; - - if(g_ctx->rom == NULL) { - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 30, 30, "No ROM"); - } else if(g_ctx->halted) { - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 30, 30, "Halted"); - } else { - if(in_menu) { - // switch(layout_mode) - // draw_menu_landscape(canvas); - draw_menu(canvas); - } else { - switch(layout_mode) { - case 0: - draw_landscape(canvas, TAMA_SCREEN_SCALE_FACTOR); // 2 - break; - case 1: - draw_landscape(canvas, 3); - break; - case 2: - draw_landscape(canvas, 4); - break; - case 3: - draw_portrait_right(canvas, TAMA_SCREEN_SCALE_FACTOR); - break; - case 4: - draw_portrait_left(canvas, TAMA_SCREEN_SCALE_FACTOR); - break; - default: - break; - } - } - } - furi_mutex_release(mutex); -} - -static void tama_p1_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - TamaEvent event = {.type = EventTypeInput, .input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -static void tama_p1_update_timer_callback(FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - TamaEvent event = {.type = EventTypeTick}; - furi_message_queue_put(event_queue, &event, 0); -} - -static void tama_p1_load_state() { - state_t* state; - uint8_t buf[4]; - bool error = false; - state = tamalib_get_state(); - - Storage* storage = furi_record_open(RECORD_STORAGE); - File* file = storage_file_alloc(storage); - if(storage_file_open(file, TAMA_SAVE_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) { - storage_file_read(file, &buf, 4); - if(buf[0] != (uint8_t)STATE_FILE_MAGIC[0] || buf[1] != (uint8_t)STATE_FILE_MAGIC[1] || - buf[2] != (uint8_t)STATE_FILE_MAGIC[2] || buf[3] != (uint8_t)STATE_FILE_MAGIC[3]) { - FURI_LOG_E(TAG, "FATAL: Wrong state file magic in \"%s\" !\n", TAMA_SAVE_PATH); - error = true; - } - - storage_file_read(file, &buf, 1); - if(buf[0] != STATE_FILE_VERSION) { - FURI_LOG_E(TAG, "FATAL: Unsupported version"); - error = true; - } - if(!error) { - FURI_LOG_D(TAG, "Reading save.bin"); - - storage_file_read(file, &buf, 2); - *(state->pc) = buf[0] | ((buf[1] & 0x1F) << 8); - - storage_file_read(file, &buf, 2); - *(state->x) = buf[0] | ((buf[1] & 0xF) << 8); - - storage_file_read(file, &buf, 2); - *(state->y) = buf[0] | ((buf[1] & 0xF) << 8); - - storage_file_read(file, &buf, 1); - *(state->a) = buf[0] & 0xF; - - storage_file_read(file, &buf, 1); - *(state->b) = buf[0] & 0xF; - - storage_file_read(file, &buf, 1); - *(state->np) = buf[0] & 0x1F; - - storage_file_read(file, &buf, 1); - *(state->sp) = buf[0]; - - storage_file_read(file, &buf, 1); - *(state->flags) = buf[0] & 0xF; - - storage_file_read(file, &buf, 4); - *(state->tick_counter) = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); - - storage_file_read(file, &buf, 4); - *(state->clk_timer_timestamp) = buf[0] | (buf[1] << 8) | (buf[2] << 16) | - (buf[3] << 24); - - storage_file_read(file, &buf, 4); - *(state->prog_timer_timestamp) = buf[0] | (buf[1] << 8) | (buf[2] << 16) | - (buf[3] << 24); - - storage_file_read(file, &buf, 1); - *(state->prog_timer_enabled) = buf[0] & 0x1; - - storage_file_read(file, &buf, 1); - *(state->prog_timer_data) = buf[0]; - - storage_file_read(file, &buf, 1); - *(state->prog_timer_rld) = buf[0]; - - storage_file_read(file, &buf, 4); - *(state->call_depth) = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); - - FURI_LOG_D(TAG, "Restoring Interupts"); - for(uint32_t i = 0; i < INT_SLOT_NUM; i++) { - storage_file_read(file, &buf, 1); - state->interrupts[i].factor_flag_reg = buf[0] & 0xF; - - storage_file_read(file, &buf, 1); - state->interrupts[i].mask_reg = buf[0] & 0xF; - - storage_file_read(file, &buf, 1); - state->interrupts[i].triggered = buf[0] & 0x1; - } - - /* First 640 half bytes correspond to the RAM */ - FURI_LOG_D(TAG, "Restoring RAM"); - for(uint32_t i = 0; i < MEM_RAM_SIZE; i++) { - storage_file_read(file, &buf, 1); - SET_RAM_MEMORY(state->memory, i + MEM_RAM_ADDR, buf[0] & 0xF); - } - - /* I/Os are from 0xF00 to 0xF7F */ - FURI_LOG_D(TAG, "Restoring I/O"); - for(uint32_t i = 0; i < MEM_IO_SIZE; i++) { - storage_file_read(file, &buf, 1); - SET_IO_MEMORY(state->memory, i + MEM_IO_ADDR, buf[0] & 0xF); - } - FURI_LOG_D(TAG, "Refreshing Hardware"); - tamalib_refresh_hw(); - } - } - - storage_file_close(file); - storage_file_free(file); - furi_record_close(RECORD_STORAGE); -} - -static void tama_p1_save_state() { - // Saving state - FURI_LOG_D(TAG, "Saving Gamestate"); - uint8_t buf[4]; - state_t* state; - uint32_t offset = 0; - state = tamalib_get_state(); - - Storage* storage = furi_record_open(RECORD_STORAGE); - File* file = storage_file_alloc(storage); - - if(storage_file_open(file, TAMA_SAVE_PATH, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { - buf[0] = (uint8_t)STATE_FILE_MAGIC[0]; - buf[1] = (uint8_t)STATE_FILE_MAGIC[1]; - buf[2] = (uint8_t)STATE_FILE_MAGIC[2]; - buf[3] = (uint8_t)STATE_FILE_MAGIC[3]; - offset += storage_file_write(file, &buf, sizeof(buf)); - - buf[0] = STATE_FILE_VERSION & 0xFF; - offset += storage_file_write(file, &buf, 1); - - buf[0] = *(state->pc) & 0xFF; - buf[1] = (*(state->pc) >> 8) & 0x1F; - offset += storage_file_write(file, &buf, 2); - - buf[0] = *(state->x) & 0xFF; - buf[1] = (*(state->x) >> 8) & 0xF; - offset += storage_file_write(file, &buf, 2); - - buf[0] = *(state->y) & 0xFF; - buf[1] = (*(state->y) >> 8) & 0xF; - offset += storage_file_write(file, &buf, 2); - - buf[0] = *(state->a) & 0xF; - offset += storage_file_write(file, &buf, 1); - - buf[0] = *(state->b) & 0xF; - offset += storage_file_write(file, &buf, 1); - - buf[0] = *(state->np) & 0x1F; - offset += storage_file_write(file, &buf, 1); - - buf[0] = *(state->sp) & 0xFF; - offset += storage_file_write(file, &buf, 1); - - buf[0] = *(state->flags) & 0xF; - offset += storage_file_write(file, &buf, 1); - - buf[0] = *(state->tick_counter) & 0xFF; - buf[1] = (*(state->tick_counter) >> 8) & 0xFF; - buf[2] = (*(state->tick_counter) >> 16) & 0xFF; - buf[3] = (*(state->tick_counter) >> 24) & 0xFF; - offset += storage_file_write(file, &buf, sizeof(buf)); - - buf[0] = *(state->clk_timer_timestamp) & 0xFF; - buf[1] = (*(state->clk_timer_timestamp) >> 8) & 0xFF; - buf[2] = (*(state->clk_timer_timestamp) >> 16) & 0xFF; - buf[3] = (*(state->clk_timer_timestamp) >> 24) & 0xFF; - offset += storage_file_write(file, &buf, sizeof(buf)); - - buf[0] = *(state->prog_timer_timestamp) & 0xFF; - buf[1] = (*(state->prog_timer_timestamp) >> 8) & 0xFF; - buf[2] = (*(state->prog_timer_timestamp) >> 16) & 0xFF; - buf[3] = (*(state->prog_timer_timestamp) >> 24) & 0xFF; - offset += storage_file_write(file, &buf, sizeof(buf)); - - buf[0] = *(state->prog_timer_enabled) & 0x1; - offset += storage_file_write(file, &buf, 1); - - buf[0] = *(state->prog_timer_data) & 0xFF; - offset += storage_file_write(file, &buf, 1); - - buf[0] = *(state->prog_timer_rld) & 0xFF; - offset += storage_file_write(file, &buf, 1); - - buf[0] = *(state->call_depth) & 0xFF; - buf[1] = (*(state->call_depth) >> 8) & 0xFF; - buf[2] = (*(state->call_depth) >> 16) & 0xFF; - buf[3] = (*(state->call_depth) >> 24) & 0xFF; - offset += storage_file_write(file, &buf, sizeof(buf)); - - for(uint32_t i = 0; i < INT_SLOT_NUM; i++) { - buf[0] = state->interrupts[i].factor_flag_reg & 0xF; - offset += storage_file_write(file, &buf, 1); - - buf[0] = state->interrupts[i].mask_reg & 0xF; - offset += storage_file_write(file, &buf, 1); - - buf[0] = state->interrupts[i].triggered & 0x1; - offset += storage_file_write(file, &buf, 1); - } - - /* First 640 half bytes correspond to the RAM */ - for(uint32_t i = 0; i < MEM_RAM_SIZE; i++) { - buf[0] = GET_RAM_MEMORY(state->memory, i + MEM_RAM_ADDR) & 0xF; - offset += storage_file_write(file, &buf, 1); - } - - /* I/Os are from 0xF00 to 0xF7F */ - for(uint32_t i = 0; i < MEM_IO_SIZE; i++) { - buf[0] = GET_IO_MEMORY(state->memory, i + MEM_IO_ADDR) & 0xF; - offset += storage_file_write(file, &buf, 1); - } - } - storage_file_close(file); - storage_file_free(file); - furi_record_close(RECORD_STORAGE); - - FURI_LOG_D(TAG, "Finished Writing %lu", offset); -} - -static int32_t tama_p1_worker(void* context) { - bool running = true; - FuriMutex* mutex = context; - while(furi_mutex_acquire(mutex, FuriWaitForever) != FuriStatusOk) furi_delay_tick(1); - - cpu_sync_ref_timestamp(); - LL_TIM_EnableCounter(TIM2); - - tama_p1_load_state(); - - while(running) { - if(furi_thread_flags_get()) { - running = false; - } else { - // FURI_LOG_D(TAG, "Stepping"); // enabling this cause blank screen somehow - // for (int i = 0; i < 100; ++i) - tamalib_step(); // tamalib_mainloop(); - } - } - LL_TIM_DisableCounter(TIM2); - furi_mutex_release(mutex); - return 0; -} - -static void tama_p1_init(TamaApp* const ctx) { - g_ctx = ctx; - memset(ctx, 0, sizeof(TamaApp)); - tama_p1_hal_init(&ctx->hal); - - // Load ROM - Storage* storage = furi_record_open(RECORD_STORAGE); - storage_common_migrate(storage, EXT_PATH("tama_p1"), STORAGE_APP_DATA_PATH_PREFIX); - FileInfo fi; - if(storage_common_stat(storage, TAMA_ROM_PATH, &fi) == FSE_OK) { - File* rom_file = storage_file_alloc(storage); - if(storage_file_open(rom_file, TAMA_ROM_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) { - ctx->rom = malloc((size_t)fi.size); - uint8_t* buf_ptr = ctx->rom; - size_t read = 0; - while(read < fi.size) { - size_t to_read = fi.size - read; - if(to_read > UINT16_MAX) to_read = UINT16_MAX; - uint16_t now_read = storage_file_read(rom_file, buf_ptr, (uint16_t)to_read); - read += now_read; - buf_ptr += now_read; - } - - // Reorder endianess of ROM - for(size_t i = 0; i < fi.size; i += 2) { - uint8_t b = ctx->rom[i]; - ctx->rom[i] = ctx->rom[i + 1]; - ctx->rom[i + 1] = b & 0xF; - } - } - - storage_file_close(rom_file); - storage_file_free(rom_file); - } - furi_record_close(RECORD_STORAGE); - - if(ctx->rom != NULL) { - // Init TIM2 - // 64KHz - - furi_hal_bus_enable(FuriHalBusTIM2); - - LL_TIM_InitTypeDef tim_init = { - .Prescaler = 999, - .CounterMode = LL_TIM_COUNTERMODE_UP, - .Autoreload = 0xFFFFFFFF, - }; - LL_TIM_Init(TIM2, &tim_init); - LL_TIM_SetClockSource(TIM2, LL_TIM_CLOCKSOURCE_INTERNAL); - LL_TIM_DisableCounter(TIM2); - LL_TIM_SetCounter(TIM2, 0); - - // Init TamaLIB - tamalib_register_hal(&ctx->hal); - tamalib_init((u12_t*)ctx->rom, NULL, 64000); - tamalib_set_speed(speed); - - // TODO: implement fast forwarding - // ctx->fast_forward_done = true; - - // Start stepping thread - ctx->thread = furi_thread_alloc(); - furi_thread_set_name(ctx->thread, "TamaLIB"); - furi_thread_set_stack_size(ctx->thread, 2 * 1024); - furi_thread_set_callback(ctx->thread, tama_p1_worker); - furi_thread_set_context(ctx->thread, g_state_mutex); - furi_thread_start(ctx->thread); - } -} - -static void tama_p1_deinit(TamaApp* const ctx) { - if(ctx->rom != NULL) { - tamalib_release(); - furi_thread_free(ctx->thread); - furi_hal_bus_disable(FuriHalBusTIM2); - free(ctx->rom); - } -} - -int32_t tama_p1_app(void* p) { - UNUSED(p); - - TamaApp* ctx = malloc(sizeof(TamaApp)); - g_state_mutex = furi_mutex_alloc(FuriMutexTypeRecursive); - tama_p1_init(ctx); - - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(TamaEvent)); - - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, tama_p1_draw_callback, g_state_mutex); - view_port_input_callback_set(view_port, tama_p1_input_callback, event_queue); - - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - FuriTimer* timer = - furi_timer_alloc(tama_p1_update_timer_callback, FuriTimerTypePeriodic, event_queue); - furi_timer_start(timer, furi_kernel_get_tick_frequency() / 30); - - // in_menu = false; - // menu_cursor = 2; - - for(bool running = true; running;) { - TamaEvent event; - FuriStatus event_status = furi_message_queue_get(event_queue, &event, FuriWaitForever); - if(event_status == FuriStatusOk) { - // Local override with acquired context - if(furi_mutex_acquire(g_state_mutex, FuriWaitForever) != FuriStatusOk) continue; - - if(event.type == EventTypeTick) { - // FURI_LOG_D(TAG, "EventTypeTick"); - view_port_update(view_port); - } else if(event.type == EventTypeInput) { - FURI_LOG_D( - TAG, - "EventTypeInput: %ld %d %d", - event.input.sequence, - event.input.key, - event.input.type); - // InputType input_type = event.input.type; // idk why this is a variable - btn_state_t tama_btn_state = 0; // BTN_STATE_RELEASED is 0 - - if(in_menu) { - // if(menu_cursor == 2 && - // (event.input.key == InputKeyUp || event.input.key == InputKeyDown)) { - // tama_btn_state = BTN_STATE_RELEASED; - // } - if(event.input.key == InputKeyBack) { - tama_btn_state = BTN_STATE_RELEASED; - in_menu = false; - } else if(event.input.key == InputKeyUp && event.input.type == InputTypePress) { - tama_btn_state = BTN_STATE_RELEASED; - if(menu_cursor > 0) { - menu_cursor -= 1; - } else { - menu_cursor = menu_items - 1; - } - if(menu_cursor >= menu_items - 2 && sub_menu_last > 0) { - sub_menu_buttons = 1; - sub_menu_last = 1; - } else { - sub_menu_buttons = 0; - sub_menu_last = 0; - } - } else if(event.input.key == InputKeyDown && event.input.type == InputTypePress) { - tama_btn_state = BTN_STATE_RELEASED; - if(menu_cursor < menu_items - 1) { - menu_cursor += 1; - } else { - menu_cursor = 0; - } - if(menu_cursor >= menu_items - 2 && sub_menu_buttons > 0) { - sub_menu_buttons = 1; - sub_menu_last = 1; - } else { - sub_menu_buttons = 0; - sub_menu_last = 0; - } - } else if(event.input.key == InputKeyLeft && event.input.type == InputTypePress) { - switch(menu_cursor) { - case 0: - switch(layout_mode) { - case 0: - layout_mode = 4; - m = InputKeyRight; - a = InputKeyUp; - b = InputKeyLeft; - c = InputKeyDown; - break; - case 1: - layout_mode -= 1; // 0 - m = InputKeyUp; - a = InputKeyLeft; - b = InputKeyDown; - c = InputKeyRight; - break; - case 2: - layout_mode -= 1; // 1 - m = InputKeyUp; - a = InputKeyLeft; - b = InputKeyDown; - c = InputKeyRight; - break; - case 3: - layout_mode -= 1; // 2 - m = InputKeyUp; - a = InputKeyLeft; - b = InputKeyDown; - c = InputKeyRight; - break; - case 4: - layout_mode -= 1; // 3 - m = InputKeyLeft; - a = InputKeyDown; - b = InputKeyRight; - c = InputKeyUp; - break; - } - break; - case 1: - speed_down(); - break; - case 2: - tama_btn_state = BTN_STATE_RELEASED; - switch(sub_menu_buttons) { - case 0: - sub_menu_buttons = 3; - break; - case 1: - case 2: - case 3: - sub_menu_buttons -= 1; - break; - default: - break; - } - break; - case menu_items - 1: - switch(sub_menu_last) { - case 0: - sub_menu_last = 2; - break; - case 1: - case 2: - sub_menu_last -= 1; - break; - default: - break; - } - break; - default: - break; - } - } else if(event.input.key == InputKeyRight && event.input.type == InputTypePress) { - switch(menu_cursor) { - case 0: - switch(layout_mode) { - case 0: - layout_mode += 1; // 1 - m = InputKeyUp; - a = InputKeyLeft; - b = InputKeyDown; - c = InputKeyRight; - break; - case 1: - layout_mode += 1; // 2 - m = InputKeyUp; - a = InputKeyLeft; - b = InputKeyDown; - c = InputKeyRight; - break; - case 2: - layout_mode += 1; // 3 - m = InputKeyLeft; - a = InputKeyDown; - b = InputKeyRight; - c = InputKeyUp; - break; - case 3: - layout_mode += 1; // 4 - m = InputKeyRight; - a = InputKeyUp; - b = InputKeyLeft; - c = InputKeyDown; - break; - case 4: - layout_mode = 0; - m = InputKeyUp; - a = InputKeyLeft; - b = InputKeyDown; - c = InputKeyRight; - break; - } - break; - case 1: - speed_up(); - break; - case 2: - tama_btn_state = BTN_STATE_RELEASED; - switch(sub_menu_buttons) { - case 0: - case 1: - case 2: - sub_menu_buttons += 1; - break; - case 3: - sub_menu_buttons = 0; - break; - default: - break; - } - break; - case menu_items - 1: - switch(sub_menu_last) { - case 0: - case 1: - sub_menu_last += 1; - break; - case 2: - sub_menu_last = 0; - break; - default: - break; - } - break; - default: - break; - } - } else if(event.input.key == InputKeyOk) { - switch(menu_cursor) { - case 0: - if(event.input.type == InputTypePress) { - switch(layout_mode) { - case 0: - layout_mode += 1; // 1 - m = InputKeyUp; - a = InputKeyLeft; - b = InputKeyDown; - c = InputKeyRight; - break; - case 1: - layout_mode += 1; // 2 - m = InputKeyUp; - a = InputKeyLeft; - b = InputKeyDown; - c = InputKeyRight; - break; - case 2: - layout_mode += 1; // 3 - m = InputKeyLeft; - a = InputKeyDown; - b = InputKeyRight; - c = InputKeyUp; - break; - case 3: - layout_mode += 1; // 4 - m = InputKeyRight; - a = InputKeyUp; - b = InputKeyLeft; - c = InputKeyDown; - break; - case 4: - layout_mode = 0; - m = InputKeyUp; - a = InputKeyLeft; - b = InputKeyDown; - c = InputKeyRight; - break; - } - } - break; - case 1: - if(event.input.type == InputTypePress) { - speed_up(); - } - break; - case 2: - if(event.input.type == InputTypePress) - tama_btn_state = BTN_STATE_PRESSED; - else if(event.input.type == InputTypeRelease) - tama_btn_state = BTN_STATE_RELEASED; - - switch(sub_menu_buttons) { - case 0: // A+C - tamalib_set_button(BTN_LEFT, tama_btn_state); - tamalib_set_button(BTN_RIGHT, tama_btn_state); - break; - case 1: // A - tamalib_set_button(BTN_LEFT, tama_btn_state); - break; - case 2: // B - tamalib_set_button(BTN_MIDDLE, tama_btn_state); - break; - case 3: // C - tamalib_set_button(BTN_RIGHT, tama_btn_state); - break; - default: - break; - } - break; - case menu_items - 1: - default: - if(event.input.type == InputTypePress) { - switch(sub_menu_last) { - case 0: // close menu - in_menu = false; - break; - case 1: // Save - if(speed != 1) { - uint8_t temp = speed; - speed = 1; - tamalib_set_speed(speed); - furi_timer_stop(timer); - tama_p1_save_state(); - furi_timer_start( - timer, furi_kernel_get_tick_frequency() / 30); - speed = temp; - tamalib_set_speed(speed); - } else { - furi_timer_stop(timer); - tama_p1_save_state(); - furi_timer_start( - timer, furi_kernel_get_tick_frequency() / 30); - } - break; - case 2: // Save & Exit - if(speed != 1) { - speed = 1; - tamalib_set_speed(speed); - } - furi_timer_stop(timer); - tama_p1_save_state(); - running = false; - break; - default: - break; - } - } - break; - } - } - } else { // out of menu // TODO: clean up code -.- - if(event.input.key == InputKeyBack && event.input.type == InputTypeLong) { - if(speed != 1) { - speed = 1; - tamalib_set_speed(speed); - } - furi_timer_stop(timer); - tama_p1_save_state(); - running = false; - } else if( - event.input.type == InputTypePress || - event.input.type == InputTypeRelease) { - if(event.input.key != InputKeyBack && event.input.key != m) { - if(event.input.type == InputTypePress) - tama_btn_state = BTN_STATE_PRESSED; - else if(event.input.type == InputTypeRelease) - tama_btn_state = BTN_STATE_RELEASED; - } else { - tama_btn_state = BTN_STATE_RELEASED; - } - if(event.input.key == m && event.input.type == InputTypePress) { - in_menu = true; - } else if(event.input.key == a) { - tamalib_set_button(BTN_LEFT, tama_btn_state); - } else if(event.input.key == b) { - tamalib_set_button(BTN_MIDDLE, tama_btn_state); - } else if(event.input.key == c) { - tamalib_set_button(BTN_RIGHT, tama_btn_state); - } else if(event.input.key == InputKeyOk) { - tamalib_set_button(BTN_MIDDLE, tama_btn_state); - } - } - } - } - furi_mutex_release(g_state_mutex); - } - // else { - // // Timeout - // FURI_LOG_D(TAG, "Timed out"); - // } - } - if(ctx->rom != NULL) { - furi_thread_flags_set(furi_thread_get_id(ctx->thread), 1); - furi_thread_join(ctx->thread); - } - furi_timer_free(timer); - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - furi_record_close(RECORD_GUI); - view_port_free(view_port); - furi_message_queue_free(event_queue); - furi_mutex_free(g_state_mutex); - tama_p1_deinit(ctx); - free(ctx); - return 0; -} diff --git a/applications/external/tama_p1/tamalib/LICENSE b/applications/external/tama_p1/tamalib/LICENSE deleted file mode 100644 index d159169d1..000000000 --- a/applications/external/tama_p1/tamalib/LICENSE +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/applications/external/tama_p1/tamalib/cpu.c b/applications/external/tama_p1/tamalib/cpu.c deleted file mode 100644 index 3f422c2d6..000000000 --- a/applications/external/tama_p1/tamalib/cpu.c +++ /dev/null @@ -1,2033 +0,0 @@ -/* - * TamaLIB - A hardware agnostic Tamagotchi P1 emulation library - * - * Copyright (C) 2021 Jean-Christophe Rona - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#include "cpu.h" -#include "hw.h" -#include "hal.h" - -#define TICK_FREQUENCY 32768 // Hz - -#define TIMER_1HZ_PERIOD 32768 // in ticks -#define TIMER_256HZ_PERIOD 128 // in ticks - -#define MASK_4B 0xF00 -#define MASK_6B 0xFC0 -#define MASK_7B 0xFE0 -#define MASK_8B 0xFF0 -#define MASK_10B 0xFFC -#define MASK_12B 0xFFF - -#define PCS (pc & 0xFF) -#define PCSL (pc & 0xF) -#define PCSH ((pc >> 4) & 0xF) -#define PCP ((pc >> 8) & 0xF) -#define PCB ((pc >> 12) & 0x1) -#define TO_PC(bank, page, step) ((step & 0xFF) | ((page & 0xF) << 8) | (bank & 0x1) << 12) -#define NBP ((np >> 4) & 0x1) -#define NPP (np & 0xF) -#define TO_NP(bank, page) ((page & 0xF) | (bank & 0x1) << 4) -#define XHL (x & 0xFF) -#define XL (x & 0xF) -#define XH ((x >> 4) & 0xF) -#define XP ((x >> 8) & 0xF) -#define YHL (y & 0xFF) -#define YL (y & 0xF) -#define YH ((y >> 4) & 0xF) -#define YP ((y >> 8) & 0xF) -#define M(n) get_memory(n) -#define SET_M(n, v) set_memory(n, v) -#define RQ(i) get_rq(i) -#define SET_RQ(i, v) set_rq(i, v) -#define SPL (sp & 0xF) -#define SPH ((sp >> 4) & 0xF) - -#define FLAG_C (0x1 << 0) -#define FLAG_Z (0x1 << 1) -#define FLAG_D (0x1 << 2) -#define FLAG_I (0x1 << 3) - -#define C !!(flags & FLAG_C) -#define Z !!(flags & FLAG_Z) -#define D !!(flags & FLAG_D) -#define I !!(flags & FLAG_I) - -#define SET_C() \ - { flags |= FLAG_C; } -#define CLEAR_C() \ - { flags &= ~FLAG_C; } -#define SET_Z() \ - { flags |= FLAG_Z; } -#define CLEAR_Z() \ - { flags &= ~FLAG_Z; } -#define SET_D() \ - { flags |= FLAG_D; } -#define CLEAR_D() \ - { flags &= ~FLAG_D; } -#define SET_I() \ - { flags |= FLAG_I; } -#define CLEAR_I() \ - { flags &= ~FLAG_I; } - -#define REG_CLK_INT_FACTOR_FLAGS 0xF00 -#define REG_SW_INT_FACTOR_FLAGS 0xF01 -#define REG_PROG_INT_FACTOR_FLAGS 0xF02 -#define REG_SERIAL_INT_FACTOR_FLAGS 0xF03 -#define REG_K00_K03_INT_FACTOR_FLAGS 0xF04 -#define REG_K10_K13_INT_FACTOR_FLAGS 0xF05 -#define REG_CLOCK_INT_MASKS 0xF10 -#define REG_SW_INT_MASKS 0xF11 -#define REG_PROG_INT_MASKS 0xF12 -#define REG_SERIAL_INT_MASKS 0xF13 -#define REG_K00_K03_INT_MASKS 0xF14 -#define REG_K10_K13_INT_MASKS 0xF15 -#define REG_PROG_TIMER_DATA_L 0xF24 -#define REG_PROG_TIMER_DATA_H 0xF25 -#define REG_PROG_TIMER_RELOAD_DATA_L 0xF26 -#define REG_PROG_TIMER_RELOAD_DATA_H 0xF27 -#define REG_K00_K03_INPUT_PORT 0xF40 -#define REG_K10_K13_INPUT_PORT 0xF42 -#define REG_K40_K43_BZ_OUTPUT_PORT 0xF54 -#define REG_CPU_OSC3_CTRL 0xF70 -#define REG_LCD_CTRL 0xF71 -#define REG_LCD_CONTRAST 0xF72 -#define REG_SVD_CTRL 0xF73 -#define REG_BUZZER_CTRL1 0xF74 -#define REG_BUZZER_CTRL2 0xF75 -#define REG_CLK_WD_TIMER_CTRL 0xF76 -#define REG_SW_TIMER_CTRL 0xF77 -#define REG_PROG_TIMER_CTRL 0xF78 -#define REG_PROG_TIMER_CLK_SEL 0xF79 - -#define INPUT_PORT_NUM 2 - -typedef struct { - char* log; - u12_t code; - u12_t mask; - u12_t shift_arg0; - u12_t mask_arg0; // != 0 only if there are two arguments - u8_t cycles; - void (*cb)(u8_t arg0, u8_t arg1); -} op_t; - -typedef struct { - u4_t states; -} input_port_t; - -/* Registers */ -static u13_t pc, next_pc; -static u12_t x, y; -static u4_t a, b; -static u5_t np; -static u8_t sp; - -/* Flags */ -static u4_t flags; - -static const u12_t* g_program = NULL; -static MEM_BUFFER_TYPE memory[MEM_BUFFER_SIZE]; - -static input_port_t inputs[INPUT_PORT_NUM] = {{0}}; - -/* Interrupts (in priority order) */ -static interrupt_t interrupts[INT_SLOT_NUM] = { - {0x0, 0x0, 0, 0x0C}, // Prog timer - {0x0, 0x0, 0, 0x0A}, // Serial interface - {0x0, 0x0, 0, 0x08}, // Input (K10-K13) - {0x0, 0x0, 0, 0x06}, // Input (K00-K03) - {0x0, 0x0, 0, 0x04}, // Stopwatch timer - {0x0, 0x0, 0, 0x02}, // Clock timer -}; - -static breakpoint_t* g_breakpoints = NULL; - -static u32_t call_depth = 0; - -static u32_t clk_timer_timestamp = 0; // in ticks -static u32_t prog_timer_timestamp = 0; // in ticks -static bool_t prog_timer_enabled = 0; -static u8_t prog_timer_data = 0; -static u8_t prog_timer_rld = 0; - -static u32_t tick_counter = 0; -static u32_t ts_freq; -static u8_t speed_ratio = 1; -static timestamp_t ref_ts; - -static state_t cpu_state = { - .pc = &pc, - .x = &x, - .y = &y, - .a = &a, - .b = &b, - .np = &np, - .sp = &sp, - .flags = &flags, - - .tick_counter = &tick_counter, - .clk_timer_timestamp = &clk_timer_timestamp, - .prog_timer_timestamp = &prog_timer_timestamp, - .prog_timer_enabled = &prog_timer_enabled, - .prog_timer_data = &prog_timer_data, - .prog_timer_rld = &prog_timer_rld, - - .call_depth = &call_depth, - - .interrupts = interrupts, - - .memory = memory, -}; - -void cpu_add_bp(breakpoint_t** list, u13_t addr) { - breakpoint_t* bp; - - bp = (breakpoint_t*)g_hal->malloc(sizeof(breakpoint_t)); - if(!bp) { - g_hal->log(LOG_ERROR, "Cannot allocate memory for breakpoint 0x%04X!\n", addr); - return; - } - - bp->addr = addr; - - if(*list != NULL) { - bp->next = *list; - } else { - /* List is empty */ - bp->next = NULL; - } - - *list = bp; -} - -void cpu_free_bp(breakpoint_t** list) { - breakpoint_t *bp = *list, *tmp; - - while(bp != NULL) { - tmp = bp->next; - g_hal->free(bp); - bp = tmp; - } - - *list = NULL; -} - -void cpu_set_speed(u8_t speed) { - speed_ratio = speed; -} - -state_t* cpu_get_state(void) { - return &cpu_state; -} - -u32_t cpu_get_depth(void) { - return call_depth; -} - -static void generate_interrupt(int_slot_t slot, u8_t bit) { - /* Set the factor flag no matter what */ - interrupts[slot].factor_flag_reg = interrupts[slot].factor_flag_reg | (0x1 << bit); - - /* Trigger the INT only if not masked */ - if(interrupts[slot].mask_reg & (0x1 << bit)) { - interrupts[slot].triggered = 1; - } -} - -void cpu_set_input_pin(pin_t pin, pin_state_t state) { - /* Set the I/O */ - inputs[pin & 0x4].states = (inputs[pin & 0x4].states & ~(0x1 << (pin & 0x3))) | - (state << (pin & 0x3)); - - /* Trigger the interrupt (TODO: handle relation register) */ - if(state == PIN_STATE_LOW) { - switch((pin & 0x4) >> 2) { - case 0: - generate_interrupt(INT_K00_K03_SLOT, pin & 0x3); - break; - - case 1: - generate_interrupt(INT_K10_K13_SLOT, pin & 0x3); - break; - } - } -} - -void cpu_sync_ref_timestamp(void) { - ref_ts = g_hal->get_timestamp(); -} - -static u4_t get_io(u12_t n) { - u4_t tmp; - - switch(n) { - case REG_CLK_INT_FACTOR_FLAGS: - /* Interrupt factor flags (clock timer) */ - tmp = interrupts[INT_CLOCK_TIMER_SLOT].factor_flag_reg; - interrupts[INT_CLOCK_TIMER_SLOT].factor_flag_reg = 0; - return tmp; - - case REG_SW_INT_FACTOR_FLAGS: - /* Interrupt factor flags (stopwatch) */ - tmp = interrupts[INT_STOPWATCH_SLOT].factor_flag_reg; - interrupts[INT_STOPWATCH_SLOT].factor_flag_reg = 0; - return tmp; - - case REG_PROG_INT_FACTOR_FLAGS: - /* Interrupt factor flags (prog timer) */ - tmp = interrupts[INT_PROG_TIMER_SLOT].factor_flag_reg; - interrupts[INT_PROG_TIMER_SLOT].factor_flag_reg = 0; - return tmp; - - case REG_SERIAL_INT_FACTOR_FLAGS: - /* Interrupt factor flags (serial) */ - tmp = interrupts[INT_SERIAL_SLOT].factor_flag_reg; - interrupts[INT_SERIAL_SLOT].factor_flag_reg = 0; - return tmp; - - case REG_K00_K03_INT_FACTOR_FLAGS: - /* Interrupt factor flags (K00-K03) */ - tmp = interrupts[INT_K00_K03_SLOT].factor_flag_reg; - interrupts[INT_K00_K03_SLOT].factor_flag_reg = 0; - return tmp; - - case REG_K10_K13_INT_FACTOR_FLAGS: - /* Interrupt factor flags (K10-K13) */ - tmp = interrupts[INT_K10_K13_SLOT].factor_flag_reg; - interrupts[INT_K10_K13_SLOT].factor_flag_reg = 0; - return tmp; - - case REG_CLOCK_INT_MASKS: - /* Clock timer interrupt masks */ - return interrupts[INT_CLOCK_TIMER_SLOT].mask_reg; - - case REG_SW_INT_MASKS: - /* Stopwatch interrupt masks */ - return interrupts[INT_STOPWATCH_SLOT].mask_reg & 0x3; - - case REG_PROG_INT_MASKS: - /* Prog timer interrupt masks */ - return interrupts[INT_PROG_TIMER_SLOT].mask_reg & 0x1; - - case REG_SERIAL_INT_MASKS: - /* Serial interface interrupt masks */ - return interrupts[INT_SERIAL_SLOT].mask_reg & 0x1; - - case REG_K00_K03_INT_MASKS: - /* Input (K00-K03) interrupt masks */ - return interrupts[INT_K00_K03_SLOT].mask_reg; - - case REG_K10_K13_INT_MASKS: - /* Input (K10-K13) interrupt masks */ - return interrupts[INT_K10_K13_SLOT].mask_reg; - - case REG_PROG_TIMER_DATA_L: - /* Prog timer data (low) */ - return prog_timer_data & 0xF; - - case REG_PROG_TIMER_DATA_H: - /* Prog timer data (high) */ - return (prog_timer_data >> 4) & 0xF; - - case REG_PROG_TIMER_RELOAD_DATA_L: - /* Prog timer reload data (low) */ - return prog_timer_rld & 0xF; - - case REG_PROG_TIMER_RELOAD_DATA_H: - /* Prog timer reload data (high) */ - return (prog_timer_rld >> 4) & 0xF; - - case REG_K00_K03_INPUT_PORT: - /* Input port (K00-K03) */ - return inputs[0].states; - - case REG_K10_K13_INPUT_PORT: - /* Input port (K10-K13) */ - return inputs[1].states; - - case REG_K40_K43_BZ_OUTPUT_PORT: - /* Output port (R40-R43) */ - return GET_IO_MEMORY(memory, n); - - case REG_CPU_OSC3_CTRL: - /* CPU/OSC3 clocks switch, CPU voltage switch */ - return GET_IO_MEMORY(memory, n); - - case REG_LCD_CTRL: - /* LCD control */ - return GET_IO_MEMORY(memory, n); - - case REG_LCD_CONTRAST: - /* LCD contrast */ - break; - - case REG_SVD_CTRL: - /* SVD */ - return GET_IO_MEMORY(memory, n) & 0x7; // Voltage always OK - - case REG_BUZZER_CTRL1: - /* Buzzer config 1 */ - return GET_IO_MEMORY(memory, n); - - case REG_BUZZER_CTRL2: - /* Buzzer config 2 */ - return GET_IO_MEMORY(memory, n) & 0x3; // Buzzer ready - - case REG_CLK_WD_TIMER_CTRL: - /* Clock/Watchdog timer reset */ - break; - - case REG_SW_TIMER_CTRL: - /* Stopwatch stop/run/reset */ - break; - - case REG_PROG_TIMER_CTRL: - /* Prog timer stop/run/reset */ - return !!prog_timer_enabled; - - case REG_PROG_TIMER_CLK_SEL: - /* Prog timer clock selection */ - break; - - default: - g_hal->log(LOG_ERROR, "Read from unimplemented I/O 0x%03X - PC = 0x%04X\n", n, pc); - } - - return 0; -} - -static void set_io(u12_t n, u4_t v) { - switch(n) { - case REG_CLOCK_INT_MASKS: - /* Clock timer interrupt masks */ - /* Assume 1Hz timer INT enabled (0x8) */ - interrupts[INT_CLOCK_TIMER_SLOT].mask_reg = v; - break; - - case REG_SW_INT_MASKS: - /* Stopwatch interrupt masks */ - /* Assume all INT disabled */ - interrupts[INT_STOPWATCH_SLOT].mask_reg = v; - break; - - case REG_PROG_INT_MASKS: - /* Prog timer interrupt masks */ - /* Assume Prog timer INT enabled (0x1) */ - interrupts[INT_PROG_TIMER_SLOT].mask_reg = v; - break; - - case REG_SERIAL_INT_MASKS: - /* Serial interface interrupt masks */ - /* Assume all INT disabled */ - interrupts[INT_K10_K13_SLOT].mask_reg = v; - break; - - case REG_K00_K03_INT_MASKS: - /* Input (K00-K03) interrupt masks */ - /* Assume all INT disabled */ - interrupts[INT_SERIAL_SLOT].mask_reg = v; - break; - - case REG_K10_K13_INT_MASKS: - /* Input (K10-K13) interrupt masks */ - /* Assume all INT disabled */ - interrupts[INT_K10_K13_SLOT].mask_reg = v; - break; - - case REG_PROG_TIMER_RELOAD_DATA_L: - /* Prog timer reload data (low) */ - prog_timer_rld = v | (prog_timer_rld & 0xF0); - break; - - case REG_PROG_TIMER_RELOAD_DATA_H: - /* Prog timer reload data (high) */ - prog_timer_rld = (prog_timer_rld & 0xF) | (v << 4); - break; - - case REG_K00_K03_INPUT_PORT: - /* Input port (K00-K03) */ - /* Write not allowed */ - break; - - case REG_K40_K43_BZ_OUTPUT_PORT: - /* Output port (R40-R43) */ - //g_hal->log(LOG_INFO, "Output/Buzzer: 0x%X\n", v); - hw_enable_buzzer(!(v & 0x8)); - break; - - case REG_CPU_OSC3_CTRL: - /* CPU/OSC3 clocks switch, CPU voltage switch */ - /* Assume 32,768 OSC1 selected, OSC3 off, battery >= 3,1V (0x1) */ - break; - - case REG_LCD_CTRL: - /* LCD control */ - break; - - case REG_LCD_CONTRAST: - /* LCD contrast */ - /* Assume medium contrast (0x8) */ - break; - - case REG_SVD_CTRL: - /* SVD */ - /* Assume battery voltage always OK (0x6) */ - break; - - case REG_BUZZER_CTRL1: - /* Buzzer config 1 */ - hw_set_buzzer_freq(v & 0x7); - break; - - case REG_BUZZER_CTRL2: - /* Buzzer config 2 */ - break; - - case REG_CLK_WD_TIMER_CTRL: - /* Clock/Watchdog timer reset */ - /* Ignore watchdog */ - break; - - case REG_SW_TIMER_CTRL: - /* Stopwatch stop/run/reset */ - break; - - case REG_PROG_TIMER_CTRL: - /* Prog timer stop/run/reset */ - if(v & 0x2) { - prog_timer_data = prog_timer_rld; - } - - if((v & 0x1) && !prog_timer_enabled) { - prog_timer_timestamp = tick_counter; - } - - prog_timer_enabled = v & 0x1; - break; - - case REG_PROG_TIMER_CLK_SEL: - /* Prog timer clock selection */ - /* Assume 256Hz, output disabled */ - break; - - default: - g_hal->log(LOG_ERROR, "Write 0x%X to unimplemented I/O 0x%03X - PC = 0x%04X\n", v, n, pc); - } -} - -static void set_lcd(u12_t n, u4_t v) { - u8_t i; - u8_t seg, com0; - - seg = ((n & 0x7F) >> 1); - com0 = (((n & 0x80) >> 7) * 8 + (n & 0x1) * 4); - - for(i = 0; i < 4; i++) { - hw_set_lcd_pin(seg, com0 + i, (v >> i) & 0x1); - } -} - -static u4_t get_memory(u12_t n) { - u4_t res = 0; - - if(n < MEM_RAM_SIZE) { - /* RAM */ - g_hal->log(LOG_MEMORY, "RAM - "); - res = GET_RAM_MEMORY(memory, n); - } else if(n >= MEM_DISPLAY1_ADDR && n < (MEM_DISPLAY1_ADDR + MEM_DISPLAY1_SIZE)) { - /* Display Memory 1 */ - g_hal->log(LOG_MEMORY, "Display Memory 1 - "); - res = GET_DISP1_MEMORY(memory, n); - } else if(n >= MEM_DISPLAY2_ADDR && n < (MEM_DISPLAY2_ADDR + MEM_DISPLAY2_SIZE)) { - /* Display Memory 2 */ - g_hal->log(LOG_MEMORY, "Display Memory 2 - "); - res = GET_DISP2_MEMORY(memory, n); - } else if(n >= MEM_IO_ADDR && n < (MEM_IO_ADDR + MEM_IO_SIZE)) { - /* I/O Memory */ - g_hal->log(LOG_MEMORY, "I/O - "); - res = get_io(n); - } else { - g_hal->log(LOG_ERROR, "Read from invalid memory address 0x%03X - PC = 0x%04X\n", n, pc); - return 0; - } - - g_hal->log(LOG_MEMORY, "Read 0x%X - Address 0x%03X - PC = 0x%04X\n", res, n, pc); - - return res; -} - -static void set_memory(u12_t n, u4_t v) { - /* Cache any data written to a valid address, and process it */ - if(n < MEM_RAM_SIZE) { - /* RAM */ - SET_RAM_MEMORY(memory, n, v); - g_hal->log(LOG_MEMORY, "RAM - "); - } else if(n >= MEM_DISPLAY1_ADDR && n < (MEM_DISPLAY1_ADDR + MEM_DISPLAY1_SIZE)) { - /* Display Memory 1 */ - SET_DISP1_MEMORY(memory, n, v); - set_lcd(n, v); - g_hal->log(LOG_MEMORY, "Display Memory 1 - "); - } else if(n >= MEM_DISPLAY2_ADDR && n < (MEM_DISPLAY2_ADDR + MEM_DISPLAY2_SIZE)) { - /* Display Memory 2 */ - SET_DISP2_MEMORY(memory, n, v); - set_lcd(n, v); - g_hal->log(LOG_MEMORY, "Display Memory 2 - "); - } else if(n >= MEM_IO_ADDR && n < (MEM_IO_ADDR + MEM_IO_SIZE)) { - /* I/O Memory */ - SET_IO_MEMORY(memory, n, v); - set_io(n, v); - g_hal->log(LOG_MEMORY, "I/O - "); - } else { - g_hal->log( - LOG_ERROR, "Write 0x%X to invalid memory address 0x%03X - PC = 0x%04X\n", v, n, pc); - return; - } - - g_hal->log(LOG_MEMORY, "Write 0x%X - Address 0x%03X - PC = 0x%04X\n", v, n, pc); -} - -void cpu_refresh_hw(void) { - static const struct range { - u12_t addr; - u12_t size; - } refresh_locs[] = { - {MEM_DISPLAY1_ADDR, MEM_DISPLAY1_SIZE}, /* Display Memory 1 */ - {MEM_DISPLAY2_ADDR, MEM_DISPLAY2_SIZE}, /* Display Memory 2 */ - {REG_BUZZER_CTRL1, 1}, /* Buzzer frequency */ - {REG_K40_K43_BZ_OUTPUT_PORT, 1}, /* Buzzer enabled */ - - {0, 0}, // end of list - }; - - for(int i = 0; refresh_locs[i].size != 0; i++) { - for(u12_t n = refresh_locs[i].addr; n < (refresh_locs[i].addr + refresh_locs[i].size); - n++) { - set_memory(n, GET_MEMORY(memory, n)); - } - } -} - -static u4_t get_rq(u12_t rq) { - switch(rq & 0x3) { - case 0x0: - return a; - - case 0x1: - return b; - - case 0x2: - return M(x); - - case 0x3: - return M(y); - } - - return 0; -} - -static void set_rq(u12_t rq, u4_t v) { - switch(rq & 0x3) { - case 0x0: - a = v; - break; - - case 0x1: - b = v; - break; - - case 0x2: - SET_M(x, v); - break; - - case 0x3: - SET_M(y, v); - break; - } -} - -/* Instructions */ -static void op_pset_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - np = arg0; -} - -static void op_jp_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - next_pc = arg0 | (np << 8); -} - -static void op_jp_c_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - if(flags & FLAG_C) { - next_pc = arg0 | (np << 8); - } -} - -static void op_jp_nc_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - if(!(flags & FLAG_C)) { - next_pc = arg0 | (np << 8); - } -} - -static void op_jp_z_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - if(flags & FLAG_Z) { - next_pc = arg0 | (np << 8); - } -} - -static void op_jp_nz_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - if(!(flags & FLAG_Z)) { - next_pc = arg0 | (np << 8); - } -} - -static void op_jpba_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - next_pc = a | (b << 4) | (np << 8); -} - -static void op_call_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - pc = (pc + 1) & 0x1FFF; // This does not actually change the PC register - SET_M(sp - 1, PCP); - SET_M(sp - 2, PCSH); - SET_M(sp - 3, PCSL); - sp = (sp - 3) & 0xFF; - next_pc = TO_PC(PCB, NPP, arg0); - call_depth++; -} - -static void op_calz_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - pc = (pc + 1) & 0x1FFF; // This does not actually change the PC register - SET_M(sp - 1, PCP); - SET_M(sp - 2, PCSH); - SET_M(sp - 3, PCSL); - sp = (sp - 3) & 0xFF; - next_pc = TO_PC(PCB, 0, arg0); - call_depth++; -} - -static void op_ret_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - next_pc = M(sp) | (M(sp + 1) << 4) | (M(sp + 2) << 8) | (PCB << 12); - sp = (sp + 3) & 0xFF; - call_depth--; -} - -static void op_rets_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - next_pc = M(sp) | (M(sp + 1) << 4) | (M(sp + 2) << 8) | (PCB << 12); - sp = (sp + 3) & 0xFF; - next_pc = (pc + 1) & 0x1FFF; - call_depth--; -} - -static void op_retd_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - next_pc = M(sp) | (M(sp + 1) << 4) | (M(sp + 2) << 8) | (PCB << 12); - sp = (sp + 3) & 0xFF; - SET_M(x, arg0 & 0xF); - SET_M(x + 1, (arg0 >> 4) & 0xF); - x = ((x + 2) & 0xFF) | (XP << 8); - call_depth--; -} - -static void op_nop5_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); -} - -static void op_nop7_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); -} - -static void op_halt_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - g_hal->halt(); -} - -static void op_inc_x_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - x = ((x + 1) & 0xFF) | (XP << 8); -} - -static void op_inc_y_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - y = ((y + 1) & 0xFF) | (YP << 8); -} - -static void op_ld_x_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - x = arg0 | (XP << 8); -} - -static void op_ld_y_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - y = arg0 | (YP << 8); -} - -static void op_ld_xp_r_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - x = XHL | (RQ(arg0) << 8); -} - -static void op_ld_xh_r_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - x = XL | (RQ(arg0) << 4) | (XP << 8); -} - -static void op_ld_xl_r_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - x = RQ(arg0) | (XH << 4) | (XP << 8); -} - -static void op_ld_yp_r_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - y = YHL | (RQ(arg0) << 8); -} - -static void op_ld_yh_r_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - y = YL | (RQ(arg0) << 4) | (YP << 8); -} - -static void op_ld_yl_r_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - y = RQ(arg0) | (YH << 4) | (YP << 8); -} - -static void op_ld_r_xp_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - SET_RQ(arg0, XP); -} - -static void op_ld_r_xh_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - SET_RQ(arg0, XH); -} - -static void op_ld_r_xl_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - SET_RQ(arg0, XL); -} - -static void op_ld_r_yp_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - SET_RQ(arg0, YP); -} - -static void op_ld_r_yh_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - SET_RQ(arg0, YH); -} - -static void op_ld_r_yl_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - SET_RQ(arg0, YL); -} - -static void op_adc_xh_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - u8_t tmp; - - tmp = XH + arg0 + C; - x = XL | ((tmp & 0xF) << 4) | (XP << 8); - if(tmp >> 4) { - SET_C(); - } else { - CLEAR_C(); - } - if(!(tmp & 0xF)) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_adc_xl_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - u8_t tmp; - - tmp = XL + arg0 + C; - x = (tmp & 0xF) | (XH << 4) | (XP << 8); - if(tmp >> 4) { - SET_C(); - } else { - CLEAR_C(); - } - if(!(tmp & 0xF)) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_adc_yh_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - u8_t tmp; - - tmp = YH + arg0 + C; - y = YL | ((tmp & 0xF) << 4) | (YP << 8); - if(tmp >> 4) { - SET_C(); - } else { - CLEAR_C(); - } - if(!(tmp & 0xF)) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_adc_yl_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - u8_t tmp; - - tmp = YL + arg0 + C; - y = (tmp & 0xF) | (YH << 4) | (YP << 8); - if(tmp >> 4) { - SET_C(); - } else { - CLEAR_C(); - } - if(!(tmp & 0xF)) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_cp_xh_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - if(XH < arg0) { - SET_C(); - } else { - CLEAR_C(); - } - if(XH == arg0) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_cp_xl_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - if(XL < arg0) { - SET_C(); - } else { - CLEAR_C(); - } - if(XL == arg0) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_cp_yh_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - if(YH < arg0) { - SET_C(); - } else { - CLEAR_C(); - } - if(YH == arg0) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_cp_yl_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - if(YL < arg0) { - SET_C(); - } else { - CLEAR_C(); - } - if(YL == arg0) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_ld_r_i_cb(u8_t arg0, u8_t arg1) { - SET_RQ(arg0, arg1); -} - -static void op_ld_r_q_cb(u8_t arg0, u8_t arg1) { - SET_RQ(arg0, RQ(arg1)); -} - -static void op_ld_a_mn_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - a = M(arg0); -} - -static void op_ld_b_mn_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - b = M(arg0); -} - -static void op_ld_mn_a_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - SET_M(arg0, a); -} - -static void op_ld_mn_b_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - SET_M(arg0, b); -} - -static void op_ldpx_mx_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - SET_M(x, arg0); - x = ((x + 1) & 0xFF) | (XP << 8); -} - -static void op_ldpx_r_cb(u8_t arg0, u8_t arg1) { - SET_RQ(arg0, RQ(arg1)); - x = ((x + 1) & 0xFF) | (XP << 8); -} - -static void op_ldpy_my_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - SET_M(y, arg0); - y = ((y + 1) & 0xFF) | (YP << 8); -} - -static void op_ldpy_r_cb(u8_t arg0, u8_t arg1) { - SET_RQ(arg0, RQ(arg1)); - y = ((y + 1) & 0xFF) | (YP << 8); -} - -static void op_lbpx_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - SET_M(x, arg0 & 0xF); - SET_M(x + 1, (arg0 >> 4) & 0xF); - x = ((x + 2) & 0xFF) | (XP << 8); -} - -static void op_set_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - flags |= arg0; -} - -static void op_rst_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - flags &= arg0; -} - -static void op_scf_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - SET_C(); -} - -static void op_rcf_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - CLEAR_C(); -} - -static void op_szf_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - SET_Z(); -} - -static void op_rzf_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - CLEAR_Z(); -} - -static void op_sdf_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - SET_D(); -} - -static void op_rdf_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - CLEAR_D(); -} - -static void op_ei_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - SET_I(); -} - -static void op_di_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - CLEAR_I(); -} - -static void op_inc_sp_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - sp = (sp + 1) & 0xFF; -} - -static void op_dec_sp_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - sp = (sp - 1) & 0xFF; -} - -static void op_push_r_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - sp = (sp - 1) & 0xFF; - SET_M(sp, RQ(arg0)); -} - -static void op_push_xp_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - sp = (sp - 1) & 0xFF; - SET_M(sp, XP); -} - -static void op_push_xh_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - sp = (sp - 1) & 0xFF; - SET_M(sp, XH); -} - -static void op_push_xl_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - sp = (sp - 1) & 0xFF; - SET_M(sp, XL); -} - -static void op_push_yp_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - sp = (sp - 1) & 0xFF; - SET_M(sp, YP); -} - -static void op_push_yh_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - sp = (sp - 1) & 0xFF; - SET_M(sp, YH); -} - -static void op_push_yl_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - sp = (sp - 1) & 0xFF; - SET_M(sp, YL); -} - -static void op_push_f_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - sp = (sp - 1) & 0xFF; - SET_M(sp, flags); -} - -static void op_pop_r_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - SET_RQ(arg0, M(sp)); - sp = (sp + 1) & 0xFF; -} - -static void op_pop_xp_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - x = XL | (XH << 4) | (M(sp) << 8); - sp = (sp + 1) & 0xFF; -} - -static void op_pop_xh_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - x = XL | (M(sp) << 4) | (XP << 8); - sp = (sp + 1) & 0xFF; -} - -static void op_pop_xl_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - x = M(sp) | (XH << 4) | (XP << 8); - sp = (sp + 1) & 0xFF; -} - -static void op_pop_yp_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - y = YL | (YH << 4) | (M(sp) << 8); - sp = (sp + 1) & 0xFF; -} - -static void op_pop_yh_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - y = YL | (M(sp) << 4) | (YP << 8); - sp = (sp + 1) & 0xFF; -} - -static void op_pop_yl_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - y = M(sp) | (YH << 4) | (YP << 8); - sp = (sp + 1) & 0xFF; -} - -static void op_pop_f_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg0); - UNUSED(arg1); - flags = M(sp); - sp = (sp + 1) & 0xFF; -} - -static void op_ld_sph_r_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - sp = SPL | (RQ(arg0) << 4); -} - -static void op_ld_spl_r_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - sp = RQ(arg0) | (SPH << 4); -} - -static void op_ld_r_sph_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - SET_RQ(arg0, SPH); -} - -static void op_ld_r_spl_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - SET_RQ(arg0, SPL); -} - -static void op_add_r_i_cb(u8_t arg0, u8_t arg1) { - u8_t tmp; - - tmp = RQ(arg0) + arg1; - if(D) { - if(tmp >= 10) { - SET_RQ(arg0, (tmp - 10) & 0xF); - SET_C(); - } else { - SET_RQ(arg0, tmp); - CLEAR_C(); - } - } else { - SET_RQ(arg0, tmp & 0xF); - if(tmp >> 4) { - SET_C(); - } else { - CLEAR_C(); - } - } - if(!RQ(arg0)) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_add_r_q_cb(u8_t arg0, u8_t arg1) { - u8_t tmp; - - tmp = RQ(arg0) + RQ(arg1); - if(D) { - if(tmp >= 10) { - SET_RQ(arg0, (tmp - 10) & 0xF); - SET_C(); - } else { - SET_RQ(arg0, tmp); - CLEAR_C(); - } - } else { - SET_RQ(arg0, tmp & 0xF); - if(tmp >> 4) { - SET_C(); - } else { - CLEAR_C(); - } - } - if(!RQ(arg0)) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_adc_r_i_cb(u8_t arg0, u8_t arg1) { - u8_t tmp; - - tmp = RQ(arg0) + arg1 + C; - if(D) { - if(tmp >= 10) { - SET_RQ(arg0, (tmp - 10) & 0xF); - SET_C(); - } else { - SET_RQ(arg0, tmp); - CLEAR_C(); - } - } else { - SET_RQ(arg0, tmp & 0xF); - if(tmp >> 4) { - SET_C(); - } else { - CLEAR_C(); - } - } - if(!RQ(arg0)) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_adc_r_q_cb(u8_t arg0, u8_t arg1) { - u8_t tmp; - - tmp = RQ(arg0) + RQ(arg1) + C; - if(D) { - if(tmp >= 10) { - SET_RQ(arg0, (tmp - 10) & 0xF); - SET_C(); - } else { - SET_RQ(arg0, tmp); - CLEAR_C(); - } - } else { - SET_RQ(arg0, tmp & 0xF); - if(tmp >> 4) { - SET_C(); - } else { - CLEAR_C(); - } - } - if(!RQ(arg0)) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_sub_cb(u8_t arg0, u8_t arg1) { - u8_t tmp; - - tmp = RQ(arg0) - RQ(arg1); - if(D) { - if(tmp >> 4) { - SET_RQ(arg0, (tmp - 6) & 0xF); - } else { - SET_RQ(arg0, tmp); - } - } else { - SET_RQ(arg0, tmp & 0xF); - } - if(tmp >> 4) { - SET_C(); - } else { - CLEAR_C(); - } - if(!RQ(arg0)) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_sbc_r_i_cb(u8_t arg0, u8_t arg1) { - u8_t tmp; - - tmp = RQ(arg0) - arg1 - C; - if(D) { - if(tmp >> 4) { - SET_RQ(arg0, (tmp - 6) & 0xF); - } else { - SET_RQ(arg0, tmp); - } - } else { - SET_RQ(arg0, tmp & 0xF); - } - if(tmp >> 4) { - SET_C(); - } else { - CLEAR_C(); - } - if(!RQ(arg0)) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_sbc_r_q_cb(u8_t arg0, u8_t arg1) { - u8_t tmp; - - tmp = RQ(arg0) - RQ(arg1) - C; - if(D) { - if(tmp >> 4) { - SET_RQ(arg0, (tmp - 6) & 0xF); - } else { - SET_RQ(arg0, tmp); - } - } else { - SET_RQ(arg0, tmp & 0xF); - } - if(tmp >> 4) { - SET_C(); - } else { - CLEAR_C(); - } - if(!RQ(arg0)) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_and_r_i_cb(u8_t arg0, u8_t arg1) { - SET_RQ(arg0, RQ(arg0) & arg1); - if(!RQ(arg0)) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_and_r_q_cb(u8_t arg0, u8_t arg1) { - SET_RQ(arg0, RQ(arg0) & RQ(arg1)); - if(!RQ(arg0)) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_or_r_i_cb(u8_t arg0, u8_t arg1) { - SET_RQ(arg0, RQ(arg0) | arg1); - if(!RQ(arg0)) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_or_r_q_cb(u8_t arg0, u8_t arg1) { - SET_RQ(arg0, RQ(arg0) | RQ(arg1)); - if(!RQ(arg0)) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_xor_r_i_cb(u8_t arg0, u8_t arg1) { - SET_RQ(arg0, RQ(arg0) ^ arg1); - if(!RQ(arg0)) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_xor_r_q_cb(u8_t arg0, u8_t arg1) { - SET_RQ(arg0, RQ(arg0) ^ RQ(arg1)); - if(!RQ(arg0)) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_cp_r_i_cb(u8_t arg0, u8_t arg1) { - if(RQ(arg0) < arg1) { - SET_C(); - } else { - CLEAR_C(); - } - if(RQ(arg0) == arg1) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_cp_r_q_cb(u8_t arg0, u8_t arg1) { - if(RQ(arg0) < RQ(arg1)) { - SET_C(); - } else { - CLEAR_C(); - } - if(RQ(arg0) == RQ(arg1)) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_fan_r_i_cb(u8_t arg0, u8_t arg1) { - if(!(RQ(arg0) & arg1)) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_fan_r_q_cb(u8_t arg0, u8_t arg1) { - if(!(RQ(arg0) & RQ(arg1))) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_rlc_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - u8_t tmp; - - tmp = (RQ(arg0) << 1) | C; - if(RQ(arg0) & 0x8) { - SET_C(); - } else { - CLEAR_C(); - } - SET_RQ(arg0, tmp & 0xF); - /* No need to set Z (issue in DS) */ -} - -static void op_rrc_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - u8_t tmp; - - tmp = (RQ(arg0) >> 1) | (C << 3); - if(RQ(arg0) & 0x1) { - SET_C(); - } else { - CLEAR_C(); - } - SET_RQ(arg0, tmp & 0xF); - /* No need to set Z (issue in DS) */ -} - -static void op_inc_mn_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - u8_t tmp; - - tmp = M(arg0) + 1; - SET_M(arg0, tmp & 0xF); - if(tmp >> 4) { - SET_C(); - } else { - CLEAR_C(); - } - if(!M(arg0)) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_dec_mn_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - u8_t tmp; - - tmp = M(arg0) - 1; - SET_M(arg0, tmp & 0xF); - if(tmp >> 4) { - SET_C(); - } else { - CLEAR_C(); - } - if(!M(arg0)) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -static void op_acpx_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - u8_t tmp; - - tmp = M(x) + RQ(arg0) + C; - if(D) { - if(tmp >= 10) { - SET_M(x, (tmp - 10) & 0xF); - SET_C(); - } else { - SET_M(x, tmp); - CLEAR_C(); - } - } else { - SET_M(x, tmp & 0xF); - if(tmp >> 4) { - SET_C(); - } else { - CLEAR_C(); - } - } - if(!M(x)) { - SET_Z(); - } else { - CLEAR_Z(); - } - x = ((x + 1) & 0xFF) | (XP << 8); -} - -static void op_acpy_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - u8_t tmp; - - tmp = M(y) + RQ(arg0) + C; - if(D) { - if(tmp >= 10) { - SET_M(y, (tmp - 10) & 0xF); - SET_C(); - } else { - SET_M(y, tmp); - CLEAR_C(); - } - } else { - SET_M(y, tmp & 0xF); - if(tmp >> 4) { - SET_C(); - } else { - CLEAR_C(); - } - } - if(!M(y)) { - SET_Z(); - } else { - CLEAR_Z(); - } - y = ((y + 1) & 0xFF) | (YP << 8); -} - -static void op_scpx_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - u8_t tmp; - - tmp = M(x) - RQ(arg0) - C; - if(D) { - if(tmp >> 4) { - SET_M(x, (tmp - 6) & 0xF); - } else { - SET_M(x, tmp); - } - } else { - SET_M(x, tmp & 0xF); - } - if(tmp >> 4) { - SET_C(); - } else { - CLEAR_C(); - } - if(!M(x)) { - SET_Z(); - } else { - CLEAR_Z(); - } - x = ((x + 1) & 0xFF) | (XP << 8); -} - -static void op_scpy_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - u8_t tmp; - - tmp = M(y) - RQ(arg0) - C; - if(D) { - if(tmp >> 4) { - SET_M(y, (tmp - 6) & 0xF); - } else { - SET_M(y, tmp); - } - } else { - SET_M(y, tmp & 0xF); - } - if(tmp >> 4) { - SET_C(); - } else { - CLEAR_C(); - } - if(!M(y)) { - SET_Z(); - } else { - CLEAR_Z(); - } - y = ((y + 1) & 0xFF) | (YP << 8); -} - -static void op_not_cb(u8_t arg0, u8_t arg1) { - UNUSED(arg1); - SET_RQ(arg0, ~RQ(arg0) & 0xF); - if(!RQ(arg0)) { - SET_Z(); - } else { - CLEAR_Z(); - } -} - -/* The E0C6S46 supported instructions */ -static const op_t ops[] = { - {"PSET #0x%02X ", 0xE40, MASK_7B, 0, 0, 5, &op_pset_cb}, // PSET - {"JP #0x%02X ", 0x000, MASK_4B, 0, 0, 5, &op_jp_cb}, // JP - {"JP C #0x%02X ", 0x200, MASK_4B, 0, 0, 5, &op_jp_c_cb}, // JP_C - {"JP NC #0x%02X ", 0x300, MASK_4B, 0, 0, 5, &op_jp_nc_cb}, // JP_NC - {"JP Z #0x%02X ", 0x600, MASK_4B, 0, 0, 5, &op_jp_z_cb}, // JP_Z - {"JP NZ #0x%02X ", 0x700, MASK_4B, 0, 0, 5, &op_jp_nz_cb}, // JP_NZ - {"JPBA ", 0xFE8, MASK_12B, 0, 0, 5, &op_jpba_cb}, // JPBA - {"CALL #0x%02X ", 0x400, MASK_4B, 0, 0, 7, &op_call_cb}, // CALL - {"CALZ #0x%02X ", 0x500, MASK_4B, 0, 0, 7, &op_calz_cb}, // CALZ - {"RET ", 0xFDF, MASK_12B, 0, 0, 7, &op_ret_cb}, // RET - {"RETS ", 0xFDE, MASK_12B, 0, 0, 12, &op_rets_cb}, // RETS - {"RETD #0x%02X ", 0x100, MASK_4B, 0, 0, 12, &op_retd_cb}, // RETD - {"NOP5 ", 0xFFB, MASK_12B, 0, 0, 5, &op_nop5_cb}, // NOP5 - {"NOP7 ", 0xFFF, MASK_12B, 0, 0, 7, &op_nop7_cb}, // NOP7 - {"HALT ", 0xFF8, MASK_12B, 0, 0, 5, &op_halt_cb}, // HALT - {"INC X #0x%02X ", 0xEE0, MASK_12B, 0, 0, 5, &op_inc_x_cb}, // INC_X - {"INC Y #0x%02X ", 0xEF0, MASK_12B, 0, 0, 5, &op_inc_y_cb}, // INC_Y - {"LD X #0x%02X ", 0xB00, MASK_4B, 0, 0, 5, &op_ld_x_cb}, // LD_X - {"LD Y #0x%02X ", 0x800, MASK_4B, 0, 0, 5, &op_ld_y_cb}, // LD_Y - {"LD XP R(#0x%02X) ", 0xE80, MASK_10B, 0, 0, 5, &op_ld_xp_r_cb}, // LD_XP_R - {"LD XH R(#0x%02X) ", 0xE84, MASK_10B, 0, 0, 5, &op_ld_xh_r_cb}, // LD_XH_R - {"LD XL R(#0x%02X) ", 0xE88, MASK_10B, 0, 0, 5, &op_ld_xl_r_cb}, // LD_XL_R - {"LD YP R(#0x%02X) ", 0xE90, MASK_10B, 0, 0, 5, &op_ld_yp_r_cb}, // LD_YP_R - {"LD YH R(#0x%02X) ", 0xE94, MASK_10B, 0, 0, 5, &op_ld_yh_r_cb}, // LD_YH_R - {"LD YL R(#0x%02X) ", 0xE98, MASK_10B, 0, 0, 5, &op_ld_yl_r_cb}, // LD_YL_R - {"LD R(#0x%02X) XP ", 0xEA0, MASK_10B, 0, 0, 5, &op_ld_r_xp_cb}, // LD_R_XP - {"LD R(#0x%02X) XH ", 0xEA4, MASK_10B, 0, 0, 5, &op_ld_r_xh_cb}, // LD_R_XH - {"LD R(#0x%02X) XL ", 0xEA8, MASK_10B, 0, 0, 5, &op_ld_r_xl_cb}, // LD_R_XL - {"LD R(#0x%02X) YP ", 0xEB0, MASK_10B, 0, 0, 5, &op_ld_r_yp_cb}, // LD_R_YP - {"LD R(#0x%02X) YH ", 0xEB4, MASK_10B, 0, 0, 5, &op_ld_r_yh_cb}, // LD_R_YH - {"LD R(#0x%02X) YL ", 0xEB8, MASK_10B, 0, 0, 5, &op_ld_r_yl_cb}, // LD_R_YL - {"ADC XH #0x%02X ", 0xA00, MASK_8B, 0, 0, 7, &op_adc_xh_cb}, // ADC_XH - {"ADC XL #0x%02X ", 0xA10, MASK_8B, 0, 0, 7, &op_adc_xl_cb}, // ADC_XL - {"ADC YH #0x%02X ", 0xA20, MASK_8B, 0, 0, 7, &op_adc_yh_cb}, // ADC_YH - {"ADC YL #0x%02X ", 0xA30, MASK_8B, 0, 0, 7, &op_adc_yl_cb}, // ADC_YL - {"CP XH #0x%02X ", 0xA40, MASK_8B, 0, 0, 7, &op_cp_xh_cb}, // CP_XH - {"CP XL #0x%02X ", 0xA50, MASK_8B, 0, 0, 7, &op_cp_xl_cb}, // CP_XL - {"CP YH #0x%02X ", 0xA60, MASK_8B, 0, 0, 7, &op_cp_yh_cb}, // CP_YH - {"CP YL #0x%02X ", 0xA70, MASK_8B, 0, 0, 7, &op_cp_yl_cb}, // CP_YL - {"LD R(#0x%02X) #0x%02X ", 0xE00, MASK_6B, 4, 0x030, 5, &op_ld_r_i_cb}, // LD_R_I - {"LD R(#0x%02X) Q(#0x%02X)", 0xEC0, MASK_8B, 2, 0x00C, 5, &op_ld_r_q_cb}, // LD_R_Q - {"LD A M(#0x%02X) ", 0xFA0, MASK_8B, 0, 0, 5, &op_ld_a_mn_cb}, // LD_A_MN - {"LD B M(#0x%02X) ", 0xFB0, MASK_8B, 0, 0, 5, &op_ld_b_mn_cb}, // LD_B_MN - {"LD M(#0x%02X) A ", 0xF80, MASK_8B, 0, 0, 5, &op_ld_mn_a_cb}, // LD_MN_A - {"LD M(#0x%02X) B ", 0xF90, MASK_8B, 0, 0, 5, &op_ld_mn_b_cb}, // LD_MN_B - {"LDPX MX #0x%02X ", 0xE60, MASK_8B, 0, 0, 5, &op_ldpx_mx_cb}, // LDPX_MX - {"LDPX R(#0x%02X) Q(#0x%02X)", 0xEE0, MASK_8B, 2, 0x00C, 5, &op_ldpx_r_cb}, // LDPX_R - {"LDPY MY #0x%02X ", 0xE70, MASK_8B, 0, 0, 5, &op_ldpy_my_cb}, // LDPY_MY - {"LDPY R(#0x%02X) Q(#0x%02X)", 0xEF0, MASK_8B, 2, 0x00C, 5, &op_ldpy_r_cb}, // LDPY_R - {"LBPX #0x%02X ", 0x900, MASK_4B, 0, 0, 5, &op_lbpx_cb}, // LBPX - {"SET #0x%02X ", 0xF40, MASK_8B, 0, 0, 7, &op_set_cb}, // SET - {"RST #0x%02X ", 0xF50, MASK_8B, 0, 0, 7, &op_rst_cb}, // RST - {"SCF ", 0xF41, MASK_12B, 0, 0, 7, &op_scf_cb}, // SCF - {"RCF ", 0xF5E, MASK_12B, 0, 0, 7, &op_rcf_cb}, // RCF - {"SZF ", 0xF42, MASK_12B, 0, 0, 7, &op_szf_cb}, // SZF - {"RZF ", 0xF5D, MASK_12B, 0, 0, 7, &op_rzf_cb}, // RZF - {"SDF ", 0xF44, MASK_12B, 0, 0, 7, &op_sdf_cb}, // SDF - {"RDF ", 0xF5B, MASK_12B, 0, 0, 7, &op_rdf_cb}, // RDF - {"EI ", 0xF48, MASK_12B, 0, 0, 7, &op_ei_cb}, // EI - {"DI ", 0xF57, MASK_12B, 0, 0, 7, &op_di_cb}, // DI - {"INC SP ", 0xFDB, MASK_12B, 0, 0, 5, &op_inc_sp_cb}, // INC_SP - {"DEC SP ", 0xFCB, MASK_12B, 0, 0, 5, &op_dec_sp_cb}, // DEC_SP - {"PUSH R(#0x%02X) ", 0xFC0, MASK_10B, 0, 0, 5, &op_push_r_cb}, // PUSH_R - {"PUSH XP ", 0xFC4, MASK_12B, 0, 0, 5, &op_push_xp_cb}, // PUSH_XP - {"PUSH XH ", 0xFC5, MASK_12B, 0, 0, 5, &op_push_xh_cb}, // PUSH_XH - {"PUSH XL ", 0xFC6, MASK_12B, 0, 0, 5, &op_push_xl_cb}, // PUSH_XL - {"PUSH YP ", 0xFC7, MASK_12B, 0, 0, 5, &op_push_yp_cb}, // PUSH_YP - {"PUSH YH ", 0xFC8, MASK_12B, 0, 0, 5, &op_push_yh_cb}, // PUSH_YH - {"PUSH YL ", 0xFC9, MASK_12B, 0, 0, 5, &op_push_yl_cb}, // PUSH_YL - {"PUSH F ", 0xFCA, MASK_12B, 0, 0, 5, &op_push_f_cb}, // PUSH_F - {"POP R(#0x%02X) ", 0xFD0, MASK_10B, 0, 0, 5, &op_pop_r_cb}, // POP_R - {"POP XP ", 0xFD4, MASK_12B, 0, 0, 5, &op_pop_xp_cb}, // POP_XP - {"POP XH ", 0xFD5, MASK_12B, 0, 0, 5, &op_pop_xh_cb}, // POP_XH - {"POP XL ", 0xFD6, MASK_12B, 0, 0, 5, &op_pop_xl_cb}, // POP_XL - {"POP YP ", 0xFD7, MASK_12B, 0, 0, 5, &op_pop_yp_cb}, // POP_YP - {"POP YH ", 0xFD8, MASK_12B, 0, 0, 5, &op_pop_yh_cb}, // POP_YH - {"POP YL ", 0xFD9, MASK_12B, 0, 0, 5, &op_pop_yl_cb}, // POP_YL - {"POP F ", 0xFDA, MASK_12B, 0, 0, 5, &op_pop_f_cb}, // POP_F - {"LD SPH R(#0x%02X) ", 0xFE0, MASK_10B, 0, 0, 5, &op_ld_sph_r_cb}, // LD_SPH_R - {"LD SPL R(#0x%02X) ", 0xFF0, MASK_10B, 0, 0, 5, &op_ld_spl_r_cb}, // LD_SPL_R - {"LD R(#0x%02X) SPH ", 0xFE4, MASK_10B, 0, 0, 5, &op_ld_r_sph_cb}, // LD_R_SPH - {"LD R(#0x%02X) SPL ", 0xFF4, MASK_10B, 0, 0, 5, &op_ld_r_spl_cb}, // LD_R_SPL - {"ADD R(#0x%02X) #0x%02X ", 0xC00, MASK_6B, 4, 0x030, 7, &op_add_r_i_cb}, // ADD_R_I - {"ADD R(#0x%02X) Q(#0x%02X)", 0xA80, MASK_8B, 2, 0x00C, 7, &op_add_r_q_cb}, // ADD_R_Q - {"ADC R(#0x%02X) #0x%02X ", 0xC40, MASK_6B, 4, 0x030, 7, &op_adc_r_i_cb}, // ADC_R_I - {"ADC R(#0x%02X) Q(#0x%02X)", 0xA90, MASK_8B, 2, 0x00C, 7, &op_adc_r_q_cb}, // ADC_R_Q - {"SUB R(#0x%02X) Q(#0x%02X)", 0xAA0, MASK_8B, 2, 0x00C, 7, &op_sub_cb}, // SUB - {"SBC R(#0x%02X) #0x%02X ", 0xB40, MASK_6B, 4, 0x030, 7, &op_sbc_r_i_cb}, // SBC_R_I - {"SBC R(#0x%02X) Q(#0x%02X)", 0xAB0, MASK_8B, 2, 0x00C, 7, &op_sbc_r_q_cb}, // SBC_R_Q - {"AND R(#0x%02X) #0x%02X ", 0xC80, MASK_6B, 4, 0x030, 7, &op_and_r_i_cb}, // AND_R_I - {"AND R(#0x%02X) Q(#0x%02X)", 0xAC0, MASK_8B, 2, 0x00C, 7, &op_and_r_q_cb}, // AND_R_Q - {"OR R(#0x%02X) #0x%02X ", 0xCC0, MASK_6B, 4, 0x030, 7, &op_or_r_i_cb}, // OR_R_I - {"OR R(#0x%02X) Q(#0x%02X)", 0xAD0, MASK_8B, 2, 0x00C, 7, &op_or_r_q_cb}, // OR_R_Q - {"XOR R(#0x%02X) #0x%02X ", 0xD00, MASK_6B, 4, 0x030, 7, &op_xor_r_i_cb}, // XOR_R_I - {"XOR R(#0x%02X) Q(#0x%02X)", 0xAE0, MASK_8B, 2, 0x00C, 7, &op_xor_r_q_cb}, // XOR_R_Q - {"CP R(#0x%02X) #0x%02X ", 0xDC0, MASK_6B, 4, 0x030, 7, &op_cp_r_i_cb}, // CP_R_I - {"CP R(#0x%02X) Q(#0x%02X)", 0xF00, MASK_8B, 2, 0x00C, 7, &op_cp_r_q_cb}, // CP_R_Q - {"FAN R(#0x%02X) #0x%02X ", 0xD80, MASK_6B, 4, 0x030, 7, &op_fan_r_i_cb}, // FAN_R_I - {"FAN R(#0x%02X) Q(#0x%02X)", 0xF10, MASK_8B, 2, 0x00C, 7, &op_fan_r_q_cb}, // FAN_R_Q - {"RLC R(#0x%02X) ", 0xAF0, MASK_8B, 0, 0, 7, &op_rlc_cb}, // RLC - {"RRC R(#0x%02X) ", 0xE8C, MASK_10B, 0, 0, 5, &op_rrc_cb}, // RRC - {"INC M(#0x%02X) ", 0xF60, MASK_8B, 0, 0, 7, &op_inc_mn_cb}, // INC_MN - {"DEC M(#0x%02X) ", 0xF70, MASK_8B, 0, 0, 7, &op_dec_mn_cb}, // DEC_MN - {"ACPX R(#0x%02X) ", 0xF28, MASK_10B, 0, 0, 7, &op_acpx_cb}, // ACPX - {"ACPY R(#0x%02X) ", 0xF2C, MASK_10B, 0, 0, 7, &op_acpy_cb}, // ACPY - {"SCPX R(#0x%02X) ", 0xF38, MASK_10B, 0, 0, 7, &op_scpx_cb}, // SCPX - {"SCPY R(#0x%02X) ", 0xF3C, MASK_10B, 0, 0, 7, &op_scpy_cb}, // SCPY - {"NOT R(#0x%02X) ", 0xD0F, 0xFCF, 4, 0, 7, &op_not_cb}, // NOT - - {NULL, 0, 0, 0, 0, 0, NULL}, -}; - -static timestamp_t wait_for_cycles(timestamp_t since, u8_t cycles) { - timestamp_t deadline; - - tick_counter += cycles; - - if(speed_ratio == 0) { - /* Emulation will be as fast as possible */ - return g_hal->get_timestamp(); - } - - deadline = since + (cycles * ts_freq) / (TICK_FREQUENCY * speed_ratio); - g_hal->sleep_until(deadline); - - return deadline; -} - -static void process_interrupts(void) { - u8_t i; - - /* Process interrupts in priority order */ - for(i = 0; i < INT_SLOT_NUM; i++) { - if(interrupts[i].triggered) { - //printf("IT %u !\n", i); - SET_M(sp - 1, PCP); - SET_M(sp - 2, PCSH); - SET_M(sp - 3, PCSL); - sp = (sp - 3) & 0xFF; - CLEAR_I(); - np = TO_NP(NBP, 1); - pc = TO_PC(PCB, 1, interrupts[i].vector); - call_depth++; - - ref_ts = wait_for_cycles(ref_ts, 12); - interrupts[i].triggered = 0; - } - } -} - -static void print_state(u8_t op_num, u12_t op, u13_t addr) { - u8_t i; - - if(!g_hal->is_log_enabled(LOG_CPU)) { - return; - } - - g_hal->log(LOG_CPU, "0x%04X: ", addr); - - for(i = 0; i < call_depth; i++) { - g_hal->log(LOG_CPU, " "); - } - - if(ops[op_num].mask_arg0 != 0) { - /* Two arguments */ - g_hal->log( - LOG_CPU, - ops[op_num].log, - (op & ops[op_num].mask_arg0) >> ops[op_num].shift_arg0, - op & ~(ops[op_num].mask | ops[op_num].mask_arg0)); - } else { - /* One argument */ - g_hal->log(LOG_CPU, ops[op_num].log, (op & ~ops[op_num].mask) >> ops[op_num].shift_arg0); - } - - if(call_depth < 10) { - for(i = 0; i < (10 - call_depth); i++) { - g_hal->log(LOG_CPU, " "); - } - } - - g_hal->log(LOG_CPU, " ; 0x%03X - ", op); - for(i = 0; i < 12; i++) { - g_hal->log(LOG_CPU, "%s", ((op >> (11 - i)) & 0x1) ? "1" : "0"); - } - g_hal->log( - LOG_CPU, - " - PC = 0x%04X, SP = 0x%02X, NP = 0x%02X, X = 0x%03X, Y = 0x%03X, A = 0x%X, B = 0x%X, F = 0x%X\n", - pc, - sp, - np, - x, - y, - a, - b, - flags); -} - -void cpu_reset(void) { - u13_t i; - - /* Registers and variables init */ - pc = TO_PC(0, 1, 0x00); // PC starts at bank 0, page 1, step 0 - np = TO_NP(0, 1); // NP starts at page 1 - a = 0; // undef - b = 0; // undef - x = 0; // undef - y = 0; // undef - sp = 0; // undef - flags = 0; - - /* Init RAM to zeros */ - for(i = 0; i < MEM_BUFFER_SIZE; i++) { - memory[i] = 0; - } - - SET_IO_MEMORY(memory, REG_K40_K43_BZ_OUTPUT_PORT, 0xF); // Output port (R40-R43) - SET_IO_MEMORY(memory, REG_LCD_CTRL, 0x8); // LCD control - /* TODO: Input relation register */ - - cpu_sync_ref_timestamp(); -} - -bool_t cpu_init(const u12_t* program, breakpoint_t* breakpoints, u32_t freq) { - g_program = program; - g_breakpoints = breakpoints; - ts_freq = freq; - - cpu_reset(); - - return 0; -} - -void cpu_release(void) { -} - -int cpu_step(void) { - u12_t op; - u8_t i; - breakpoint_t* bp = g_breakpoints; - static u8_t previous_cycles = 0; - - op = g_program[pc]; - - /* Lookup the OP code */ - for(i = 0; ops[i].log != NULL; i++) { - if((op & ops[i].mask) == ops[i].code) { - break; - } - } - - if(ops[i].log == NULL) { - g_hal->log(LOG_ERROR, "Unknown op-code 0x%X (pc = 0x%04X)\n", op, pc); - return 1; - } - - next_pc = (pc + 1) & 0x1FFF; - - /* Display the operation along with the current state of the processor */ - print_state(i, op, pc); - - /* Match the speed of the real processor - * NOTE: For better accuracy, the final wait should happen here, however - * the downside is that all interrupts will likely be delayed by one OP - */ - ref_ts = wait_for_cycles(ref_ts, previous_cycles); - - /* Process the OP code */ - if(ops[i].cb != NULL) { - if(ops[i].mask_arg0 != 0) { - /* Two arguments */ - ops[i].cb( - (op & ops[i].mask_arg0) >> ops[i].shift_arg0, - op & ~(ops[i].mask | ops[i].mask_arg0)); - } else { - /* One arguments */ - ops[i].cb((op & ~ops[i].mask) >> ops[i].shift_arg0, 0); - } - } - - /* Prepare for the next instruction */ - pc = next_pc; - previous_cycles = ops[i].cycles; - - if(i > 0) { - /* OP code is not PSET, reset NP */ - np = (pc >> 8) & 0x1F; - } - - /* Handle timers using the internal tick counter */ - if(tick_counter - clk_timer_timestamp >= TIMER_1HZ_PERIOD) { - do { - clk_timer_timestamp += TIMER_1HZ_PERIOD; - } while(tick_counter - clk_timer_timestamp >= TIMER_1HZ_PERIOD); - - generate_interrupt(INT_CLOCK_TIMER_SLOT, 3); - } - - if(prog_timer_enabled && tick_counter - prog_timer_timestamp >= TIMER_256HZ_PERIOD) { - do { - prog_timer_timestamp += TIMER_256HZ_PERIOD; - prog_timer_data--; - - if(prog_timer_data == 0) { - prog_timer_data = prog_timer_rld; - generate_interrupt(INT_PROG_TIMER_SLOT, 0); - } - } while(tick_counter - prog_timer_timestamp >= TIMER_256HZ_PERIOD); - } - - /* Check if there is any pending interrupt */ - if(I && i > 0) { // Do not process interrupts after a PSET operation - process_interrupts(); - } - - /* Check if we could pause the execution */ - while(bp != NULL) { - if(bp->addr == pc) { - return 1; - } - - bp = bp->next; - } - - return 0; -} diff --git a/applications/external/tama_p1/tamalib/cpu.h b/applications/external/tama_p1/tamalib/cpu.h deleted file mode 100644 index 4405103b2..000000000 --- a/applications/external/tama_p1/tamalib/cpu.h +++ /dev/null @@ -1,215 +0,0 @@ -/* - * TamaLIB - A hardware agnostic Tamagotchi P1 emulation library - * - * Copyright (C) 2021 Jean-Christophe Rona - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#ifndef _CPU_H_ -#define _CPU_H_ - -#include "hal.h" - -#define MEMORY_SIZE 4096 // 4096 x 4 bits (640 x 4 bits of RAM) - -#define MEM_RAM_ADDR 0x000 -#define MEM_RAM_SIZE 0x280 -#define MEM_DISPLAY1_ADDR 0xE00 -#define MEM_DISPLAY1_SIZE 0x050 -#define MEM_DISPLAY2_ADDR 0xE80 -#define MEM_DISPLAY2_SIZE 0x050 -#define MEM_IO_ADDR 0xF00 -#define MEM_IO_SIZE 0x080 - -/* Define this if you want to reduce the footprint of the memory buffer from 4096 u4_t (most likely bytes) - * to 464 u8_t (bytes for sure), while increasing slightly the number of operations needed to read/write from/to it. - */ -#define LOW_FOOTPRINT - -#ifdef LOW_FOOTPRINT -/* Invalid memory areas are not buffered to reduce the footprint of the library in memory */ -#define MEM_BUFFER_SIZE (MEM_RAM_SIZE + MEM_DISPLAY1_SIZE + MEM_DISPLAY2_SIZE + MEM_IO_SIZE) / 2 - -/* Maps the CPU memory to the memory buffer */ -#define RAM_TO_MEMORY(n) ((n - MEM_RAM_ADDR) / 2) -#define DISP1_TO_MEMORY(n) ((n - MEM_DISPLAY1_ADDR + MEM_RAM_SIZE) / 2) -#define DISP2_TO_MEMORY(n) ((n - MEM_DISPLAY2_ADDR + MEM_RAM_SIZE + MEM_DISPLAY1_SIZE) / 2) -#define IO_TO_MEMORY(n) \ - ((n - MEM_IO_ADDR + MEM_RAM_SIZE + MEM_DISPLAY1_SIZE + MEM_DISPLAY2_SIZE) / 2) - -#define SET_RAM_MEMORY(buffer, n, v) \ - { \ - buffer[RAM_TO_MEMORY(n)] = (buffer[RAM_TO_MEMORY(n)] & ~(0xF << (((n) % 2) << 2))) | \ - ((v)&0xF) << (((n) % 2) << 2); \ - } -#define SET_DISP1_MEMORY(buffer, n, v) \ - { \ - buffer[DISP1_TO_MEMORY(n)] = (buffer[DISP1_TO_MEMORY(n)] & ~(0xF << (((n) % 2) << 2))) | \ - ((v)&0xF) << (((n) % 2) << 2); \ - } -#define SET_DISP2_MEMORY(buffer, n, v) \ - { \ - buffer[DISP2_TO_MEMORY(n)] = (buffer[DISP2_TO_MEMORY(n)] & ~(0xF << (((n) % 2) << 2))) | \ - ((v)&0xF) << (((n) % 2) << 2); \ - } -#define SET_IO_MEMORY(buffer, n, v) \ - { \ - buffer[IO_TO_MEMORY(n)] = (buffer[IO_TO_MEMORY(n)] & ~(0xF << (((n) % 2) << 2))) | \ - ((v)&0xF) << (((n) % 2) << 2); \ - } -#define SET_MEMORY(buffer, n, v) \ - { \ - if((n) < (MEM_RAM_ADDR + MEM_RAM_SIZE)) { \ - SET_RAM_MEMORY(buffer, n, v); \ - } else if((n) < MEM_DISPLAY1_ADDR) { \ - /* INVALID_MEMORY */ \ - } else if((n) < (MEM_DISPLAY1_ADDR + MEM_DISPLAY1_SIZE)) { \ - SET_DISP1_MEMORY(buffer, n, v); \ - } else if((n) < MEM_DISPLAY2_ADDR) { \ - /* INVALID_MEMORY */ \ - } else if((n) < (MEM_DISPLAY2_ADDR + MEM_DISPLAY2_SIZE)) { \ - SET_DISP2_MEMORY(buffer, n, v); \ - } else if((n) < MEM_IO_ADDR) { \ - /* INVALID_MEMORY */ \ - } else if((n) < (MEM_IO_ADDR + MEM_IO_SIZE)) { \ - SET_IO_MEMORY(buffer, n, v); \ - } else { \ - /* INVALID_MEMORY */ \ - } \ - } - -#define GET_RAM_MEMORY(buffer, n) ((buffer[RAM_TO_MEMORY(n)] >> (((n) % 2) << 2)) & 0xF) -#define GET_DISP1_MEMORY(buffer, n) ((buffer[DISP1_TO_MEMORY(n)] >> (((n) % 2) << 2)) & 0xF) -#define GET_DISP2_MEMORY(buffer, n) ((buffer[DISP2_TO_MEMORY(n)] >> (((n) % 2) << 2)) & 0xF) -#define GET_IO_MEMORY(buffer, n) ((buffer[IO_TO_MEMORY(n)] >> (((n) % 2) << 2)) & 0xF) -#define GET_MEMORY(buffer, n) \ - ((buffer \ - [((n) < (MEM_RAM_ADDR + MEM_RAM_SIZE)) ? RAM_TO_MEMORY(n) : \ - ((n) < MEM_DISPLAY1_ADDR) ? 0 : \ - ((n) < (MEM_DISPLAY1_ADDR + MEM_DISPLAY1_SIZE)) ? DISP1_TO_MEMORY(n) : \ - ((n) < MEM_DISPLAY2_ADDR) ? 0 : \ - ((n) < (MEM_DISPLAY2_ADDR + MEM_DISPLAY2_SIZE)) ? DISP2_TO_MEMORY(n) : \ - ((n) < MEM_IO_ADDR) ? 0 : \ - ((n) < (MEM_IO_ADDR + MEM_IO_SIZE)) ? IO_TO_MEMORY(n) : \ - 0] >> \ - (((n) % 2) << 2)) & \ - 0xF) - -#define MEM_BUFFER_TYPE u8_t -#else -#define MEM_BUFFER_SIZE MEMORY_SIZE - -#define SET_MEMORY(buffer, n, v) \ - { buffer[n] = v; } -#define SET_RAM_MEMORY(buffer, n, v) SET_MEMORY(buffer, n, v) -#define SET_DISP1_MEMORY(buffer, n, v) SET_MEMORY(buffer, n, v) -#define SET_DISP2_MEMORY(buffer, n, v) SET_MEMORY(buffer, n, v) -#define SET_IO_MEMORY(buffer, n, v) SET_MEMORY(buffer, n, v) - -#define GET_MEMORY(buffer, n) (buffer[n]) -#define GET_RAM_MEMORY(buffer, n) GET_MEMORY(buffer, n) -#define GET_DISP1_MEMORY(buffer, n) GET_MEMORY(buffer, n) -#define GET_DISP2_MEMORY(buffer, n) GET_MEMORY(buffer, n) -#define GET_IO_MEMORY(buffer, n) GET_MEMORY(buffer, n) - -#define MEM_BUFFER_TYPE u4_t -#endif - -typedef struct breakpoint { - u13_t addr; - struct breakpoint* next; -} breakpoint_t; - -/* Pins (TODO: add other pins) */ -typedef enum { - PIN_K00 = 0x0, - PIN_K01 = 0x1, - PIN_K02 = 0x2, - PIN_K03 = 0x3, - PIN_K10 = 0X4, - PIN_K11 = 0X5, - PIN_K12 = 0X6, - PIN_K13 = 0X7, -} pin_t; - -typedef enum { - PIN_STATE_LOW = 0, - PIN_STATE_HIGH = 1, -} pin_state_t; - -typedef enum { - INT_PROG_TIMER_SLOT = 0, - INT_SERIAL_SLOT = 1, - INT_K10_K13_SLOT = 2, - INT_K00_K03_SLOT = 3, - INT_STOPWATCH_SLOT = 4, - INT_CLOCK_TIMER_SLOT = 5, - INT_SLOT_NUM, -} int_slot_t; - -typedef struct { - u4_t factor_flag_reg; - u4_t mask_reg; - bool_t triggered; /* 1 if triggered, 0 otherwise */ - u8_t vector; -} interrupt_t; - -typedef struct { - u13_t* pc; - u12_t* x; - u12_t* y; - u4_t* a; - u4_t* b; - u5_t* np; - u8_t* sp; - u4_t* flags; - - u32_t* tick_counter; - u32_t* clk_timer_timestamp; - u32_t* prog_timer_timestamp; - bool_t* prog_timer_enabled; - u8_t* prog_timer_data; - u8_t* prog_timer_rld; - - u32_t* call_depth; - - interrupt_t* interrupts; - - MEM_BUFFER_TYPE* memory; -} state_t; - -void cpu_add_bp(breakpoint_t** list, u13_t addr); -void cpu_free_bp(breakpoint_t** list); - -void cpu_set_speed(u8_t speed); - -state_t* cpu_get_state(void); - -u32_t cpu_get_depth(void); - -void cpu_set_input_pin(pin_t pin, pin_state_t state); - -void cpu_sync_ref_timestamp(void); - -void cpu_refresh_hw(void); - -void cpu_reset(void); - -bool_t cpu_init(const u12_t* program, breakpoint_t* breakpoints, u32_t freq); -void cpu_release(void); - -int cpu_step(void); - -#endif /* _CPU_H_ */ diff --git a/applications/external/tama_p1/tamalib/hal.h b/applications/external/tama_p1/tamalib/hal.h deleted file mode 100644 index 84140befb..000000000 --- a/applications/external/tama_p1/tamalib/hal.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * TamaLIB - A hardware agnostic Tamagotchi P1 emulation library - * - * Copyright (C) 2021 Jean-Christophe Rona - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#ifndef _HAL_H_ -#define _HAL_H_ - -#include "../hal_types.h" - -#ifndef NULL -#define NULL 0 -#endif - -typedef enum { - LOG_ERROR = 0x1, - LOG_INFO = (0x1 << 1), - LOG_MEMORY = (0x1 << 2), - LOG_CPU = (0x1 << 3), -} log_level_t; - -/* The Hardware Abstraction Layer - * NOTE: This structure acts as an abstraction layer between TamaLIB and the OS/SDK. - * All pointers MUST be implemented, but some implementations can be left empty. - */ -typedef struct { - /* Memory allocation functions - * NOTE: Needed only if breakpoints support is required. - */ - void* (*malloc)(u32_t size); - void (*free)(void* ptr); - - /* What to do if the CPU has halted - */ - void (*halt)(void); - - /* Log related function - * NOTE: Needed only if log messages are required. - */ - bool_t (*is_log_enabled)(log_level_t level); - void (*log)(log_level_t level, char* buff, ...); - - /* Clock related functions - * NOTE: Timestamps granularity is configured with tamalib_init(), an accuracy - * of ~30 us (1/32768) is required for a cycle accurate emulation. - */ - void (*sleep_until)(timestamp_t ts); - timestamp_t (*get_timestamp)(void); - - /* Screen related functions - * NOTE: In case of direct hardware access to pixels, the set_XXXX() functions - * (called for each pixel/icon update) can directly drive them, otherwise they - * should just store the data in a buffer and let update_screen() do the actual - * rendering (at 30 fps). - */ - void (*update_screen)(void); - void (*set_lcd_matrix)(u8_t x, u8_t y, bool_t val); - void (*set_lcd_icon)(u8_t icon, bool_t val); - - /* Sound related functions - * NOTE: set_frequency() changes the output frequency of the sound, while - * play_frequency() decides whether the sound should be heard or not. - */ - void (*set_frequency)(u32_t freq); - void (*play_frequency)(bool_t en); - - /* Event handler from the main app (if any) - * NOTE: This function usually handles button related events, states loading/saving ... - */ - int (*handler)(void); -} hal_t; - -extern hal_t* g_hal; - -#endif /* _HAL_H_ */ diff --git a/applications/external/tama_p1/tamalib/hal_types.h.template b/applications/external/tama_p1/tamalib/hal_types.h.template deleted file mode 100644 index 38c4d212c..000000000 --- a/applications/external/tama_p1/tamalib/hal_types.h.template +++ /dev/null @@ -1,32 +0,0 @@ -/* - * TamaLIB - A hardware agnostic Tamagotchi P1 emulation library - * - * Copyright (C) 2021 Jean-Christophe Rona - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#ifndef _HAL_TYPES_H_ -#define _HAL_TYPES_H_ - -typedef unsigned char bool_t; -typedef unsigned char u4_t; -typedef unsigned char u5_t; -typedef unsigned char u8_t; -typedef unsigned short u12_t; -typedef unsigned short u13_t; -typedef unsigned int u32_t; -typedef unsigned int timestamp_t; // WARNING: Must be an unsigned type to properly handle wrapping (u32 wraps in around 1h11m when expressed in us) - -#endif /* _HAL_TYPES_H_ */ diff --git a/applications/external/tama_p1/tamalib/hw.c b/applications/external/tama_p1/tamalib/hw.c deleted file mode 100644 index 0a91f2a78..000000000 --- a/applications/external/tama_p1/tamalib/hw.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * TamaLIB - A hardware agnostic Tamagotchi P1 emulation library - * - * Copyright (C) 2021 Jean-Christophe Rona - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#include "hw.h" -#include "cpu.h" -#include "hal.h" - -/* SEG -> LCD mapping */ -static u8_t seg_pos[40] = {0, 1, 2, 3, 4, 5, 6, 7, 32, 8, 9, 10, 11, 12, - 13, 14, 15, 33, 34, 35, 31, 30, 29, 28, 27, 26, 25, 24, - 36, 23, 22, 21, 20, 19, 18, 17, 16, 37, 38, 39}; - -bool_t hw_init(void) { - /* Buttons are active LOW */ - cpu_set_input_pin(PIN_K00, PIN_STATE_HIGH); - cpu_set_input_pin(PIN_K01, PIN_STATE_HIGH); - cpu_set_input_pin(PIN_K02, PIN_STATE_HIGH); - - return 0; -} - -void hw_release(void) { -} - -void hw_set_lcd_pin(u8_t seg, u8_t com, u8_t val) { - if(seg_pos[seg] < LCD_WIDTH) { - g_hal->set_lcd_matrix(seg_pos[seg], com, val); - } else { - /* - * IC n -> seg-com|... - * IC 0 -> 8-0 |18-3 |19-2 - * IC 1 -> 8-1 |17-0 |19-3 - * IC 2 -> 8-2 |17-1 |37-12|38-13|39-14 - * IC 3 -> 8-3 |17-2 |18-1 |19-0 - * IC 4 -> 28-12|37-13|38-14|39-15 - * IC 5 -> 28-13|37-14|38-15 - * IC 6 -> 28-14|37-15|39-12 - * IC 7 -> 28-15|38-12|39-13 - */ - if(seg == 8 && com < 4) { - g_hal->set_lcd_icon(com, val); - } else if(seg == 28 && com >= 12) { - g_hal->set_lcd_icon(com - 8, val); - } - } -} - -void hw_set_button(button_t btn, btn_state_t state) { - pin_state_t pin_state = (state == BTN_STATE_PRESSED) ? PIN_STATE_LOW : PIN_STATE_HIGH; - - switch(btn) { - case BTN_LEFT: - cpu_set_input_pin(PIN_K02, pin_state); - break; - - case BTN_MIDDLE: - cpu_set_input_pin(PIN_K01, pin_state); - break; - - case BTN_RIGHT: - cpu_set_input_pin(PIN_K00, pin_state); - break; - } -} - -void hw_set_buzzer_freq(u4_t freq) { - u32_t snd_freq = 0; - - switch(freq) { - case 0: - /* 4096.0 Hz */ - snd_freq = 40960; - break; - - case 1: - /* 3276.8 Hz */ - snd_freq = 32768; - break; - - case 2: - /* 2730.7 Hz */ - snd_freq = 27307; - break; - - case 3: - /* 2340.6 Hz */ - snd_freq = 23406; - break; - - case 4: - /* 2048.0 Hz */ - snd_freq = 20480; - break; - - case 5: - /* 1638.4 Hz */ - snd_freq = 16384; - break; - - case 6: - /* 1365.3 Hz */ - snd_freq = 13653; - break; - - case 7: - /* 1170.3 Hz */ - snd_freq = 11703; - break; - } - - if(snd_freq != 0) { - g_hal->set_frequency(snd_freq); - } -} - -void hw_enable_buzzer(bool_t en) { - g_hal->play_frequency(en); -} diff --git a/applications/external/tama_p1/tamalib/hw.h b/applications/external/tama_p1/tamalib/hw.h deleted file mode 100644 index 853515b39..000000000 --- a/applications/external/tama_p1/tamalib/hw.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * TamaLIB - A hardware agnostic Tamagotchi P1 emulation library - * - * Copyright (C) 2021 Jean-Christophe Rona - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#ifndef _HW_H_ -#define _HW_H_ - -#include "hal.h" - -#define LCD_WIDTH 32 -#define LCD_HEIGHT 16 - -#define ICON_NUM 8 - -typedef enum { - BTN_STATE_RELEASED = 0, - BTN_STATE_PRESSED, -} btn_state_t; - -typedef enum { - BTN_LEFT = 0, - BTN_MIDDLE, - BTN_RIGHT, -} button_t; - -bool_t hw_init(void); -void hw_release(void); - -void hw_set_lcd_pin(u8_t seg, u8_t com, u8_t val); -void hw_set_button(button_t btn, btn_state_t state); - -void hw_set_buzzer_freq(u4_t freq); -void hw_enable_buzzer(bool_t en); - -#endif /* _HW_H_ */ diff --git a/applications/external/tama_p1/tamalib/tamalib.c b/applications/external/tama_p1/tamalib/tamalib.c deleted file mode 100644 index 92a19678c..000000000 --- a/applications/external/tama_p1/tamalib/tamalib.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * TamaLIB - A hardware agnostic Tamagotchi P1 emulation library - * - * Copyright (C) 2021 Jean-Christophe Rona - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#include "tamalib.h" -#include "hw.h" -#include "cpu.h" -#include "hal.h" - -#define DEFAULT_FRAMERATE 30 // fps - -static exec_mode_t exec_mode = EXEC_MODE_RUN; - -static u32_t step_depth = 0; - -static timestamp_t screen_ts = 0; - -static u32_t ts_freq; - -static u8_t g_framerate = DEFAULT_FRAMERATE; - -hal_t* g_hal; - -bool_t tamalib_init(const u12_t* program, breakpoint_t* breakpoints, u32_t freq) { - bool_t res = 0; - - res |= cpu_init(program, breakpoints, freq); - res |= hw_init(); - - ts_freq = freq; - - return res; -} - -void tamalib_release(void) { - hw_release(); - cpu_release(); -} - -void tamalib_set_framerate(u8_t framerate) { - g_framerate = framerate; -} - -u8_t tamalib_get_framerate(void) { - return g_framerate; -} - -void tamalib_register_hal(hal_t* hal) { - g_hal = hal; -} - -void tamalib_set_exec_mode(exec_mode_t mode) { - exec_mode = mode; - step_depth = cpu_get_depth(); - cpu_sync_ref_timestamp(); -} - -void tamalib_step(void) { - if(exec_mode == EXEC_MODE_PAUSE) { - return; - } - - if(cpu_step()) { - exec_mode = EXEC_MODE_PAUSE; - step_depth = cpu_get_depth(); - } else { - switch(exec_mode) { - case EXEC_MODE_PAUSE: - case EXEC_MODE_RUN: - break; - - case EXEC_MODE_STEP: - exec_mode = EXEC_MODE_PAUSE; - break; - - case EXEC_MODE_NEXT: - if(cpu_get_depth() <= step_depth) { - exec_mode = EXEC_MODE_PAUSE; - step_depth = cpu_get_depth(); - } - break; - - case EXEC_MODE_TO_CALL: - if(cpu_get_depth() > step_depth) { - exec_mode = EXEC_MODE_PAUSE; - step_depth = cpu_get_depth(); - } - break; - - case EXEC_MODE_TO_RET: - if(cpu_get_depth() < step_depth) { - exec_mode = EXEC_MODE_PAUSE; - step_depth = cpu_get_depth(); - } - break; - } - } -} - -void tamalib_mainloop(void) { - timestamp_t ts; - - while(!g_hal->handler()) { - tamalib_step(); - - /* Update the screen @ g_framerate fps */ - ts = g_hal->get_timestamp(); - if(ts - screen_ts >= ts_freq / g_framerate) { - screen_ts = ts; - g_hal->update_screen(); - } - } -} diff --git a/applications/external/tama_p1/tamalib/tamalib.h b/applications/external/tama_p1/tamalib/tamalib.h deleted file mode 100644 index 570f845eb..000000000 --- a/applications/external/tama_p1/tamalib/tamalib.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * TamaLIB - A hardware agnostic Tamagotchi P1 emulation library - * - * Copyright (C) 2021 Jean-Christophe Rona - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#ifndef _TAMALIB_H_ -#define _TAMALIB_H_ - -#include "cpu.h" -#include "hw.h" -#include "hal.h" - -#define tamalib_set_button(btn, state) hw_set_button(btn, state) - -#define tamalib_set_speed(speed) cpu_set_speed(speed) - -#define tamalib_get_state() cpu_get_state() -#define tamalib_refresh_hw() cpu_refresh_hw() - -#define tamalib_reset() cpu_reset() - -#define tamalib_add_bp(list, addr) cpu_add_bp(list, addr) -#define tamalib_free_bp(list) cpu_free_bp(list) - -typedef enum { - EXEC_MODE_PAUSE, - EXEC_MODE_RUN, - EXEC_MODE_STEP, - EXEC_MODE_NEXT, - EXEC_MODE_TO_CALL, - EXEC_MODE_TO_RET, -} exec_mode_t; - -void tamalib_release(void); -bool_t tamalib_init(const u12_t* program, breakpoint_t* breakpoints, u32_t freq); - -void tamalib_set_framerate(u8_t framerate); -u8_t tamalib_get_framerate(void); - -void tamalib_register_hal(hal_t* hal); - -void tamalib_set_exec_mode(exec_mode_t mode); - -/* NOTE: Only one of these two functions must be used in the main application - * (tamalib_step() should be used only if tamalib_mainloop() does not fit the - * main application execution flow). - */ -void tamalib_step(void); -void tamalib_mainloop(void); - -#endif /* _TAMALIB_H_ */ diff --git a/applications/external/text2sam/application.fam b/applications/external/text2sam/application.fam deleted file mode 100644 index 3a0765680..000000000 --- a/applications/external/text2sam/application.fam +++ /dev/null @@ -1,20 +0,0 @@ -App( - appid="text2sam", - name="Text to SAM", - apptype=FlipperAppType.EXTERNAL, - entry_point="sam_app", - cdefines=["APP_SAM"], - # requires=["gui",], - requires=[ - "gui", - "dialogs", - ], - stack_size=4 * 1024, - # stack_size=2 * 1024, - fap_icon="icon.png", - fap_category="Media", - fap_author="@Round-Pi & (Fixes by @Willy-JL)", - fap_weburl="https://github.com/Round-Pi/flipperzero-text2sam", - fap_version="1.1", - fap_description="Convert text to speech on your Flipper Zero with SAM (Software Automatic Mouth).", -) diff --git a/applications/external/text2sam/icon.png b/applications/external/text2sam/icon.png deleted file mode 100644 index d13fa0c07..000000000 Binary files a/applications/external/text2sam/icon.png and /dev/null differ diff --git a/applications/external/text2sam/sam_app.cpp b/applications/external/text2sam/sam_app.cpp deleted file mode 100644 index 3c7e42a74..000000000 --- a/applications/external/text2sam/sam_app.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "stm32_sam.h" - -#define TAG "SAM" -#define SAM_SAVE_PATH APP_DATA_PATH("message.txt") -#define TEXT_BUFFER_SIZE 256 -STM32SAM voice; - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef struct { - EventType type; - InputEvent input; -} PluginEvent; - -typedef struct { - ViewDispatcher* view_dispatcher; - TextInput* text_input; - char input[TEXT_BUFFER_SIZE]; -} AppState; - -AppState* app_state; - -static void say_something(char* something) { - if(furi_hal_speaker_is_mine() || furi_hal_speaker_acquire(1000)) { - voice.begin(); - voice.say(something); - furi_hal_speaker_release(); - } -} - -static void text_input_callback(void* ctx) { - AppState* app_state = (AppState*)ctx; - //FURI_LOG_D(TAG, "Input text: %s", app_state->input); - - // underscore_to_space(app_state->input); - for(int i = 0; app_state->input[i] != '\0'; i++) { - if(app_state->input[i] == '_') { - app_state->input[i] = ' '; - } - } - - say_something(app_state->input); -} - -static bool back_event_callback(void* ctx) { - const AppState* app_state = (AppState*)ctx; - view_dispatcher_stop(app_state->view_dispatcher); - return true; -} - -static void sam_state_init(AppState* const app_state) { - app_state->view_dispatcher = view_dispatcher_alloc(); - app_state->text_input = text_input_alloc(); -} - -static void sam_state_free(AppState* const app_state) { - text_input_free(app_state->text_input); - view_dispatcher_remove_view(app_state->view_dispatcher, 0); - view_dispatcher_free(app_state->view_dispatcher); - free(app_state); -} - -static void save_message(FuriString* save_string) { - Storage* storage = (Storage*)furi_record_open(RECORD_STORAGE); - File* file = storage_file_alloc(storage); - if(storage_file_open(file, SAM_SAVE_PATH, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { - storage_file_write(file, save_string, TEXT_BUFFER_SIZE); - } - storage_file_close(file); - storage_file_free(file); - furi_record_close(RECORD_STORAGE); -} - -static bool load_messages() { - Storage* storage = (Storage*)furi_record_open(RECORD_STORAGE); - storage_common_migrate(storage, EXT_PATH("sam.txt"), SAM_SAVE_PATH); - File* file = storage_file_alloc(storage); - uint16_t bytes_read = 0; - if(storage_file_open(file, SAM_SAVE_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) { - bytes_read = storage_file_read(file, app_state->input, TEXT_BUFFER_SIZE); - } - storage_file_close(file); - storage_file_free(file); - furi_record_close(RECORD_STORAGE); - return bytes_read == TEXT_BUFFER_SIZE; -} - -extern "C" int32_t sam_app(void* p) { - UNUSED(p); - app_state = (AppState*)malloc(sizeof(AppState)); - - FURI_LOG_D(TAG, "Running sam_state_init"); - sam_state_init(app_state); - - FURI_LOG_D(TAG, "Assigning text input callback"); - - load_messages(); - text_input_set_result_callback( - app_state->text_input, - text_input_callback, - app_state, - app_state->input, - TEXT_BUFFER_SIZE, - false); //clear default text - text_input_set_header_text(app_state->text_input, "Input"); - - Gui* gui = (Gui*)furi_record_open(RECORD_GUI); - - view_dispatcher_enable_queue(app_state->view_dispatcher); - - FURI_LOG_D(TAG, "Adding text input view to dispatcher"); - view_dispatcher_add_view( - app_state->view_dispatcher, 0, text_input_get_view(app_state->text_input)); - - FURI_LOG_D(TAG, "Attaching view dispatcher to GUI"); - view_dispatcher_attach_to_gui(app_state->view_dispatcher, gui, ViewDispatcherTypeFullscreen); - FURI_LOG_D(TAG, "starting view dispatcher"); - view_dispatcher_set_navigation_event_callback(app_state->view_dispatcher, back_event_callback); - view_dispatcher_set_event_callback_context(app_state->view_dispatcher, app_state); - view_dispatcher_switch_to_view(app_state->view_dispatcher, 0); - view_dispatcher_run(app_state->view_dispatcher); - - save_message((FuriString*)app_state->input); - - furi_record_close(RECORD_GUI); - sam_state_free(app_state); - - return 0; -} diff --git a/applications/external/text2sam/stm32_sam.cpp b/applications/external/text2sam/stm32_sam.cpp deleted file mode 100644 index c77543c03..000000000 --- a/applications/external/text2sam/stm32_sam.cpp +++ /dev/null @@ -1,5703 +0,0 @@ - -#include "stm32_sam.h" -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////////////////// -// -// All -// -//////////////////////////////////////////////////////////////////////////////////////////// - -char input[256 + 1] = {0}; //tab39445 -//standard sam sound - -unsigned char wait1 = 7; -unsigned char wait2 = 6; - -unsigned char A, X, Y; -unsigned char mem44; -unsigned char mem47; -unsigned char mem49; -unsigned char mem39; -unsigned char mem50; -unsigned char mem51; -unsigned char mem53; -unsigned char mem56; -unsigned char mem59 = 0; - -unsigned char phonemeIndexOutput[60]; //tab47296 -unsigned char stressOutput[60]; //tab47365 -unsigned char phonemeLengthOutput[60]; //tab47416 - -// contains the soundbuffer position -int bufferpos; - -//////////////////////////////////////////////////////////////////////////////////////////// -// -// Sam Tabs -// -//////////////////////////////////////////////////////////////////////////////////////////// - -//tab40672 -const unsigned char stressInputTable[] = {'*', '1', '2', '3', '4', '5', '6', '7', '8'}; - -//tab40682 -const unsigned char signInputTable1[] = { - ' ', '.', '?', ',', '-', 'I', 'I', 'E', 'A', 'A', 'A', 'A', 'U', 'A', 'I', 'E', 'U', - 'O', 'R', 'L', 'W', 'Y', 'W', 'R', 'L', 'W', 'Y', 'M', 'N', 'N', 'D', 'Q', 'S', 'S', - 'F', 'T', '/', '/', 'Z', 'Z', 'V', 'D', 'C', '*', 'J', '*', '*', '*', 'E', 'A', 'O', - 'A', 'O', 'U', 'B', '*', '*', 'D', '*', '*', 'G', '*', '*', 'G', '*', '*', 'P', '*', - '*', 'T', '*', '*', 'K', '*', '*', 'K', '*', '*', 'U', 'U', 'U'}; - -//tab40763 -const unsigned char signInputTable2[] = { - '*', '*', '*', '*', '*', 'Y', 'H', 'H', 'E', 'A', 'H', 'O', 'H', 'X', 'X', 'R', 'X', - 'H', 'X', 'X', 'X', 'X', 'H', '*', '*', '*', '*', '*', '*', 'X', 'X', '*', '*', 'H', - '*', 'H', 'H', 'X', '*', 'H', '*', 'H', 'H', '*', '*', '*', '*', '*', 'Y', 'Y', 'Y', - 'W', 'W', 'W', '*', '*', '*', '*', '*', '*', '*', '*', '*', 'X', '*', '*', '*', '*', - '*', '*', '*', '*', '*', '*', '*', 'X', '*', '*', 'L', 'M', 'N'}; - -//loc_9F8C -const unsigned char flags[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x84, 0x84, 0xA4, - 0xA4, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x44, 0x44, 0x44, 0x44, 0x44, 0x4C, - 0x4C, 0x4C, 0x48, 0x4C, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x44, 0x44, 0x44, - 0x48, 0x40, 0x4C, 0x44, 0x00, 0x00, 0xB4, 0xB4, 0xB4, 0x94, 0x94, 0x94, 0x4E, 0x4E, - 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4B, 0x4B, 0x4B, 0x4B, - 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x80, 0xC1, 0xC1 - -}; - -//??? flags overlap flags2 -//loc_9FDA -const unsigned char flags2[] = { - 0x80, 0xC1, 0xC1, 0xC1, 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0C, 0x08, 0x04, 0x40, - 0x24, 0x20, 0x20, 0x24, 0x00, 0x00, 0x24, 0x20, 0x20, 0x24, 0x20, 0x20, 0x00, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - -//tab45616??? -const unsigned char phonemeStressedLengthTable[] = { - 0x00, 0x12, 0x12, 0x12, 8, 0xB, 9, 0xB, 0xE, 0xF, 0xB, 0x10, 0xC, 6, 6, 0xE, - 0xC, 0xE, 0xC, 0xB, 8, 8, 0xB, 0xA, 9, 8, 8, 8, 8, 8, 3, 5, - 2, 2, 2, 2, 2, 2, 6, 6, 8, 6, 6, 2, 9, 4, 2, 1, - 0xE, 0xF, 0xF, 0xF, 0xE, 0xE, 8, 2, 2, 7, 2, 1, 7, 2, 2, 7, - 2, 2, 8, 2, 2, 6, 2, 2, 7, 2, 4, 7, 1, 4, 5, 5}; - -//tab45536??? -const unsigned char phonemeLengthTable[] = { - 0, 0x12, 0x12, 0x12, 8, 8, 8, 8, 8, 0xB, 6, 0xC, 0xA, 5, 5, 0xB, 0xA, 0xA, 0xA, 9, - 8, 7, 9, 7, 6, 8, 6, 7, 7, 7, 2, 5, 2, 2, 2, 2, 2, 2, 6, 6, - 7, 6, 6, 2, 8, 3, 1, 0x1E, 0xD, 0xC, 0xC, 0xC, 0xE, 9, 6, 1, 2, 5, 1, 1, - 6, 1, 2, 6, 1, 2, 8, 2, 2, 4, 2, 2, 6, 1, 4, 6, 1, 4, 0xC7, 0xFF}; - -/* - - Ind | phoneme | flags | - -----|---------|----------| - 0 | * | 00000000 | - 1 | .* | 00000000 | - 2 | ?* | 00000000 | - 3 | ,* | 00000000 | - 4 | -* | 00000000 | - - VOWELS - 5 | IY | 10100100 | - 6 | IH | 10100100 | - 7 | EH | 10100100 | - 8 | AE | 10100100 | - 9 | AA | 10100100 | - 10 | AH | 10100100 | - 11 | AO | 10000100 | - 17 | OH | 10000100 | - 12 | UH | 10000100 | - 16 | UX | 10000100 | - 15 | ER | 10000100 | - 13 | AX | 10100100 | - 14 | IX | 10100100 | - - DIPHTONGS - 48 | EY | 10110100 | - 49 | AY | 10110100 | - 50 | OY | 10110100 | - 51 | AW | 10010100 | - 52 | OW | 10010100 | - 53 | UW | 10010100 | - - - 21 | YX | 10000100 | - 20 | WX | 10000100 | - 18 | RX | 10000100 | - 19 | LX | 10000100 | - 37 | /X | 01000000 | - 30 | DX | 01001000 | - - - 22 | WH | 01000100 | - - - VOICED CONSONANTS - 23 | R* | 01000100 | - 24 | L* | 01000100 | - 25 | W* | 01000100 | - 26 | Y* | 01000100 | - 27 | M* | 01001100 | - 28 | N* | 01001100 | - 29 | NX | 01001100 | - 54 | B* | 01001110 | - 57 | D* | 01001110 | - 60 | G* | 01001110 | - 44 | J* | 01001100 | - 38 | Z* | 01000100 | - 39 | ZH | 01000100 | - 40 | V* | 01000100 | - 41 | DH | 01000100 | - - unvoiced CONSONANTS - 32 | S* | 01000000 | - 33 | SH | 01000000 | - 34 | F* | 01000000 | - 35 | TH | 01000000 | - 66 | P* | 01001011 | - 69 | T* | 01001011 | - 72 | K* | 01001011 | - 42 | CH | 01001000 | - 36 | /H | 01000000 | - - 43 | ** | 01000000 | - 45 | ** | 01000100 | - 46 | ** | 00000000 | - 47 | ** | 00000000 | - - - 55 | ** | 01001110 | - 56 | ** | 01001110 | - 58 | ** | 01001110 | - 59 | ** | 01001110 | - 61 | ** | 01001110 | - 62 | ** | 01001110 | - 63 | GX | 01001110 | - 64 | ** | 01001110 | - 65 | ** | 01001110 | - 67 | ** | 01001011 | - 68 | ** | 01001011 | - 70 | ** | 01001011 | - 71 | ** | 01001011 | - 73 | ** | 01001011 | - 74 | ** | 01001011 | - 75 | KX | 01001011 | - 76 | ** | 01001011 | - 77 | ** | 01001011 | - - - SPECIAL - 78 | UL | 10000000 | - 79 | UM | 11000001 | - 80 | UN | 11000001 | - 31 | Q* | 01001100 | - -*/ - -//////////////////////////////////////////////////////////////////////////////////////////// -// -// RenderTabs -// -//////////////////////////////////////////////////////////////////////////////////////////// - -const unsigned char tab48426[5] = {0x18, 0x1A, 0x17, 0x17, 0x17}; - -const unsigned char tab47492[] = {0, 0, 0xE0, 0xE6, 0xEC, 0xF3, 0xF9, 0, 6, 0xC, 6}; - -const unsigned char amplitudeRescale[] = { - 0, - 1, - 2, - 2, - 2, - 3, - 3, - 4, - 4, - 5, - 6, - 8, - 9, - 0xB, - 0xD, - 0xF, - 0 //17 elements? -}; - -// Used to decide which phoneme's blend lengths. The candidate with the lower score is selected. -// tab45856 -const unsigned char blendRank[] = {0, 0x1F, 0x1F, 0x1F, 0x1F, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 5, 5, 2, 0xA, 2, 8, - 5, 5, 0xB, 0xA, 9, 8, 8, 0xA0, 8, 8, - 0x17, 0x1F, 0x12, 0x12, 0x12, 0x12, 0x1E, 0x1E, 0x14, 0x14, - 0x14, 0x14, 0x17, 0x17, 0x1A, 0x1A, 0x1D, 0x1D, 2, 2, - 2, 2, 2, 2, 0x1A, 0x1D, 0x1B, 0x1A, 0x1D, 0x1B, - 0x1A, 0x1D, 0x1B, 0x1A, 0x1D, 0x1B, 0x17, 0x1D, 0x17, 0x17, - 0x1D, 0x17, 0x17, 0x1D, 0x17, 0x17, 0x1D, 0x17, 0x17, 0x17}; - -// Number of frames at the end of a phoneme devoted to interpolating to next phoneme's final value -//tab45696 -const unsigned char outBlendLength[] = {0, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 3, 2, 4, 4, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 0, 1, 0, 1, 0, 5, - 5, 5, 5, 5, 4, 4, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, - 0, 1, 2, 0, 2, 2, 0, 1, 3, 0, 2, 3, 0, 2, 0xA0, 0xA0}; - -// Number of frames at beginning of a phoneme devoted to interpolating to phoneme's final value -// tab45776 -const unsigned char inBlendLength[] = {0, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 3, 3, 4, 4, 3, 3, 3, 3, 3, 1, 2, 3, 2, 1, - 3, 3, 3, 3, 1, 1, 3, 3, 3, 2, 2, 3, 2, 3, 0, 0, - 5, 5, 5, 5, 4, 4, 2, 0, 2, 2, 0, 3, 2, 0, 4, 2, - 0, 3, 2, 0, 2, 2, 0, 2, 3, 0, 3, 3, 0, 3, 0xB0, 0xA0}; - -// Looks like it's used as bit flags -// High bits masked by 248 (11111000) -// -// 32: S* 241 11110001 -// 33: SH 226 11100010 -// 34: F* 211 11010011 -// 35: TH 187 10111011 -// 36: /H 124 01111100 -// 37: /X 149 10010101 -// 38: Z* 1 00000001 -// 39: ZH 2 00000010 -// 40: V* 3 00000011 -// 41: DH 3 00000011 -// 43: ** 114 01110010 -// 45: ** 2 00000010 -// 67: ** 27 00011011 -// 70: ** 25 00011001 -// tab45936 -const unsigned char sampledConsonantFlags[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xF1, 0xE2, 0xD3, 0xBB, 0x7C, 0x95, 1, 2, - 3, 3, 0, 0x72, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x1B, 0, 0, 0x19, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - -//tab45056 -unsigned char freq1data[] = { - 0x00, 0x13, 0x13, 0x13, 0x13, 0xA, 0xE, 0x12, 0x18, 0x1A, 0x16, 0x14, 0x10, 0x14, 0xE, 0x12, - 0xE, 0x12, 0x12, 0x10, 0xC, 0xE, 0xA, 0x12, 0xE, 0xA, 8, 6, 6, 6, 6, 0x11, - 6, 6, 6, 6, 0xE, 0x10, 9, 0xA, 8, 0xA, 6, 6, 6, 5, 6, 0, - 0x12, 0x1A, 0x14, 0x1A, 0x12, 0xC, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 0xA, 0xA, 6, 6, 6, 0x2C, 0x13}; - -//tab451356 -unsigned char freq2data[] = {0x00, 0x43, 0x43, 0x43, 0x43, 0x54, 0x48, 0x42, 0x3E, 0x28, - 0x2C, 0x1E, 0x24, 0x2C, 0x48, 0x30, 0x24, 0x1E, 0x32, 0x24, - 0x1C, 0x44, 0x18, 0x32, 0x1E, 0x18, 0x52, 0x2E, 0x36, 0x56, - 0x36, 0x43, 0x49, 0x4F, 0x1A, 0x42, 0x49, 0x25, 0x33, 0x42, - 0x28, 0x2F, 0x4F, 0x4F, 0x42, 0x4F, 0x6E, 0x00, 0x48, 0x26, - 0x1E, 0x2A, 0x1E, 0x22, 0x1A, 0x1A, 0x1A, 0x42, 0x42, 0x42, - 0x6E, 0x6E, 0x6E, 0x54, 0x54, 0x54, 0x1A, 0x1A, 0x1A, 0x42, - 0x42, 0x42, 0x6D, 0x56, 0x6D, 0x54, 0x54, 0x54, 0x7F, 0x7F}; -//tab45216 -unsigned char freq3data[] = {0x00, 0x5B, 0x5B, 0x5B, 0x5B, 0x6E, 0x5D, 0x5B, 0x58, 0x59, - 0x57, 0x58, 0x52, 0x59, 0x5D, 0x3E, 0x52, 0x58, 0x3E, 0x6E, - 0x50, 0x5D, 0x5A, 0x3C, 0x6E, 0x5A, 0x6E, 0x51, 0x79, 0x65, - 0x79, 0x5B, 0x63, 0x6A, 0x51, 0x79, 0x5D, 0x52, 0x5D, 0x67, - 0x4C, 0x5D, 0x65, 0x65, 0x79, 0x65, 0x79, 0x00, 0x5A, 0x58, - 0x58, 0x58, 0x58, 0x52, 0x51, 0x51, 0x51, 0x79, 0x79, 0x79, - 0x70, 0x6E, 0x6E, 0x5E, 0x5E, 0x5E, 0x51, 0x51, 0x51, 0x79, - 0x79, 0x79, 0x65, 0x65, 0x70, 0x5E, 0x5E, 0x5E, 0x08, 0x01}; - -//////////////////////////////////////////////////////////////////////////////////////////// -// -// Reciter -// -//////////////////////////////////////////////////////////////////////////////////////////// - -unsigned char inputtemp[256]; // secure copy of input tab36096 - -//////////////////////////////////////////////////////////////////////////////////////////// -// -// Render -// -//////////////////////////////////////////////////////////////////////////////////////////// - -//timetable for more accurate c64 simulation -int timetable[5][5] = { - {162, 167, 167, 127, 128}, - {226, 60, 60, 0, 0}, - {225, 60, 59, 0, 0}, - {200, 0, 0, 54, 55}, - {199, 0, 0, 54, 54}}; - -unsigned oldtimetableindex; - -const unsigned char ampl1data[] = {0, 0, 0, 0, 0, 0xD, 0xD, 0xE, 0xF, 0xF, 0xF, 0xF, - 0xF, 0xC, 0xD, 0xC, 0xF, 0xF, 0xD, 0xD, 0xD, 0xE, 0xD, 0xC, - 0xD, 0xD, 0xD, 0xC, 9, 9, 0, 0, 0, 0, 0, 0, - 0, 0, 0xB, 0xB, 0xB, 0xB, 0, 0, 1, 0xB, 0, 2, - 0xE, 0xF, 0xF, 0xF, 0xF, 0xD, 2, 4, 0, 2, 4, 0, - 1, 4, 0, 1, 4, 0, 0, 0, 0, 0, 0, 0, - 0, 0xC, 0, 0, 0, 0, 0xF, 0xF}; - -const unsigned char ampl2data[] = { - 0, 0, 0, 0, 0, 0xA, 0xB, 0xD, 0xE, 0xD, 0xC, 0xC, 0xB, 9, 0xB, 0xB, 0xC, 0xC, 0xC, 8, - 8, 0xC, 8, 0xA, 8, 8, 0xA, 3, 9, 6, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, - 3, 4, 0, 0, 0, 5, 0xA, 2, 0xE, 0xD, 0xC, 0xD, 0xC, 8, 0, 1, 0, 0, 1, 0, - 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0xA, 0, 0, 0xA, 0, 0, 0}; - -const unsigned char ampl3data[] = {0, 0, 0, 0, 0, 8, 7, 8, 8, 1, 1, 0, 1, 0, 7, 5, - 1, 0, 6, 1, 0, 7, 0, 5, 1, 0, 8, 0, 0, 3, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0xE, 1, - 9, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 5, 0, 0x13, 0x10}; - -//tab42240 -const signed char sinus[256] = { - 0, 3, 6, 9, 12, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, - 49, 51, 54, 57, 60, 63, 65, 68, 71, 73, 76, 78, 81, 83, 85, 88, - 90, 92, 94, 96, 98, 100, 102, 104, 106, 107, 109, 111, 112, 113, 115, 116, - 117, 118, 120, 121, 122, 122, 123, 124, 125, 125, 126, 126, 126, 127, 127, 127, - 127, 127, 127, 127, 126, 126, 126, 125, 125, 124, 123, 122, 122, 121, 120, 118, - 117, 116, 115, 113, 112, 111, 109, 107, 106, 104, 102, 100, 98, 96, 94, 92, - 90, 88, 85, 83, 81, 78, 76, 73, 71, 68, 65, 63, 60, 57, 54, 51, - 49, 46, 43, 40, 37, 34, 31, 28, 25, 22, 19, 16, 12, 9, 6, 3, - 0, -3, -6, -9, -12, -16, -19, -22, -25, -28, -31, -34, -37, -40, -43, -46, - -49, -51, -54, -57, -60, -63, -65, -68, -71, -73, -76, -78, -81, -83, -85, -88, - -90, -92, -94, -96, -98, -100, -102, -104, -106, -107, -109, -111, -112, -113, -115, -116, - -117, -118, -120, -121, -122, -122, -123, -124, -125, -125, -126, -126, -126, -127, -127, -127, - -127, -127, -127, -127, -126, -126, -126, -125, -125, -124, -123, -122, -122, -121, -120, -118, - -117, -116, -115, -113, -112, -111, -109, -107, -106, -104, -102, -100, -98, -96, -94, -92, - -90, -88, -85, -83, -81, -78, -76, -73, -71, -68, -65, -63, -60, -57, -54, -51, - -49, -46, -43, -40, -37, -34, -31, -28, -25, -22, -19, -16, -12, -9, -6, -3}; - -//tab42496 -const unsigned char rectangle[] = { - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, - 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, - 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, - 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, - 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, - 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, - 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, - 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, - 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, - 0x70}; - -//random data ? -const unsigned char sampleTable[0x500] = { - //00 - - 0x38, - 0x84, - 0x6B, - 0x19, - 0xC6, - 0x63, - 0x18, - 0x86, - 0x73, - 0x98, - 0xC6, - 0xB1, - 0x1C, - 0xCA, - 0x31, - 0x8C, - 0xC7, - 0x31, - 0x88, - 0xC2, - 0x30, - 0x98, - 0x46, - 0x31, - 0x18, - 0xC6, - 0x35, - 0xC, - 0xCA, - 0x31, - 0xC, - 0xC6 - //20 - , - 0x21, - 0x10, - 0x24, - 0x69, - 0x12, - 0xC2, - 0x31, - 0x14, - 0xC4, - 0x71, - 8, - 0x4A, - 0x22, - 0x49, - 0xAB, - 0x6A, - 0xA8, - 0xAC, - 0x49, - 0x51, - 0x32, - 0xD5, - 0x52, - 0x88, - 0x93, - 0x6C, - 0x94, - 0x22, - 0x15, - 0x54, - 0xD2, - 0x25 - //40 - , - 0x96, - 0xD4, - 0x50, - 0xA5, - 0x46, - 0x21, - 8, - 0x85, - 0x6B, - 0x18, - 0xC4, - 0x63, - 0x10, - 0xCE, - 0x6B, - 0x18, - 0x8C, - 0x71, - 0x19, - 0x8C, - 0x63, - 0x35, - 0xC, - 0xC6, - 0x33, - 0x99, - 0xCC, - 0x6C, - 0xB5, - 0x4E, - 0xA2, - 0x99 - //60 - , - 0x46, - 0x21, - 0x28, - 0x82, - 0x95, - 0x2E, - 0xE3, - 0x30, - 0x9C, - 0xC5, - 0x30, - 0x9C, - 0xA2, - 0xB1, - 0x9C, - 0x67, - 0x31, - 0x88, - 0x66, - 0x59, - 0x2C, - 0x53, - 0x18, - 0x84, - 0x67, - 0x50, - 0xCA, - 0xE3, - 0xA, - 0xAC, - 0xAB, - 0x30 - //80 - , - 0xAC, - 0x62, - 0x30, - 0x8C, - 0x63, - 0x10, - 0x94, - 0x62, - 0xB1, - 0x8C, - 0x82, - 0x28, - 0x96, - 0x33, - 0x98, - 0xD6, - 0xB5, - 0x4C, - 0x62, - 0x29, - 0xA5, - 0x4A, - 0xB5, - 0x9C, - 0xC6, - 0x31, - 0x14, - 0xD6, - 0x38, - 0x9C, - 0x4B, - 0xB4 - //A0 - , - 0x86, - 0x65, - 0x18, - 0xAE, - 0x67, - 0x1C, - 0xA6, - 0x63, - 0x19, - 0x96, - 0x23, - 0x19, - 0x84, - 0x13, - 8, - 0xA6, - 0x52, - 0xAC, - 0xCA, - 0x22, - 0x89, - 0x6E, - 0xAB, - 0x19, - 0x8C, - 0x62, - 0x34, - 0xC4, - 0x62, - 0x19, - 0x86, - 0x63 - //C0 - , - 0x18, - 0xC4, - 0x23, - 0x58, - 0xD6, - 0xA3, - 0x50, - 0x42, - 0x54, - 0x4A, - 0xAD, - 0x4A, - 0x25, - 0x11, - 0x6B, - 0x64, - 0x89, - 0x4A, - 0x63, - 0x39, - 0x8A, - 0x23, - 0x31, - 0x2A, - 0xEA, - 0xA2, - 0xA9, - 0x44, - 0xC5, - 0x12, - 0xCD, - 0x42 - //E0 - , - 0x34, - 0x8C, - 0x62, - 0x18, - 0x8C, - 0x63, - 0x11, - 0x48, - 0x66, - 0x31, - 0x9D, - 0x44, - 0x33, - 0x1D, - 0x46, - 0x31, - 0x9C, - 0xC6, - 0xB1, - 0xC, - 0xCD, - 0x32, - 0x88, - 0xC4, - 0x73, - 0x18, - 0x86, - 0x73, - 8, - 0xD6, - 0x63, - 0x58 - //100 - , - 7, - 0x81, - 0xE0, - 0xF0, - 0x3C, - 7, - 0x87, - 0x90, - 0x3C, - 0x7C, - 0xF, - 0xC7, - 0xC0, - 0xC0, - 0xF0, - 0x7C, - 0x1E, - 7, - 0x80, - 0x80, - 0, - 0x1C, - 0x78, - 0x70, - 0xF1, - 0xC7, - 0x1F, - 0xC0, - 0xC, - 0xFE, - 0x1C, - 0x1F - //120 - , - 0x1F, - 0xE, - 0xA, - 0x7A, - 0xC0, - 0x71, - 0xF2, - 0x83, - 0x8F, - 3, - 0xF, - 0xF, - 0xC, - 0, - 0x79, - 0xF8, - 0x61, - 0xE0, - 0x43, - 0xF, - 0x83, - 0xE7, - 0x18, - 0xF9, - 0xC1, - 0x13, - 0xDA, - 0xE9, - 0x63, - 0x8F, - 0xF, - 0x83 - //140 - , - 0x83, - 0x87, - 0xC3, - 0x1F, - 0x3C, - 0x70, - 0xF0, - 0xE1, - 0xE1, - 0xE3, - 0x87, - 0xB8, - 0x71, - 0xE, - 0x20, - 0xE3, - 0x8D, - 0x48, - 0x78, - 0x1C, - 0x93, - 0x87, - 0x30, - 0xE1, - 0xC1, - 0xC1, - 0xE4, - 0x78, - 0x21, - 0x83, - 0x83, - 0xC3 - //160 - , - 0x87, - 6, - 0x39, - 0xE5, - 0xC3, - 0x87, - 7, - 0xE, - 0x1C, - 0x1C, - 0x70, - 0xF4, - 0x71, - 0x9C, - 0x60, - 0x36, - 0x32, - 0xC3, - 0x1E, - 0x3C, - 0xF3, - 0x8F, - 0xE, - 0x3C, - 0x70, - 0xE3, - 0xC7, - 0x8F, - 0xF, - 0xF, - 0xE, - 0x3C - //180 - , - 0x78, - 0xF0, - 0xE3, - 0x87, - 6, - 0xF0, - 0xE3, - 7, - 0xC1, - 0x99, - 0x87, - 0xF, - 0x18, - 0x78, - 0x70, - 0x70, - 0xFC, - 0xF3, - 0x10, - 0xB1, - 0x8C, - 0x8C, - 0x31, - 0x7C, - 0x70, - 0xE1, - 0x86, - 0x3C, - 0x64, - 0x6C, - 0xB0, - 0xE1 - //1A0 - , - 0xE3, - 0xF, - 0x23, - 0x8F, - 0xF, - 0x1E, - 0x3E, - 0x38, - 0x3C, - 0x38, - 0x7B, - 0x8F, - 7, - 0xE, - 0x3C, - 0xF4, - 0x17, - 0x1E, - 0x3C, - 0x78, - 0xF2, - 0x9E, - 0x72, - 0x49, - 0xE3, - 0x25, - 0x36, - 0x38, - 0x58, - 0x39, - 0xE2, - 0xDE - //1C0 - , - 0x3C, - 0x78, - 0x78, - 0xE1, - 0xC7, - 0x61, - 0xE1, - 0xE1, - 0xB0, - 0xF0, - 0xF0, - 0xC3, - 0xC7, - 0xE, - 0x38, - 0xC0, - 0xF0, - 0xCE, - 0x73, - 0x73, - 0x18, - 0x34, - 0xB0, - 0xE1, - 0xC7, - 0x8E, - 0x1C, - 0x3C, - 0xF8, - 0x38, - 0xF0, - 0xE1 - //1E0 - , - 0xC1, - 0x8B, - 0x86, - 0x8F, - 0x1C, - 0x78, - 0x70, - 0xF0, - 0x78, - 0xAC, - 0xB1, - 0x8F, - 0x39, - 0x31, - 0xDB, - 0x38, - 0x61, - 0xC3, - 0xE, - 0xE, - 0x38, - 0x78, - 0x73, - 0x17, - 0x1E, - 0x39, - 0x1E, - 0x38, - 0x64, - 0xE1, - 0xF1, - 0xC1 - //200 - , - 0x4E, - 0xF, - 0x40, - 0xA2, - 2, - 0xC5, - 0x8F, - 0x81, - 0xA1, - 0xFC, - 0x12, - 8, - 0x64, - 0xE0, - 0x3C, - 0x22, - 0xE0, - 0x45, - 7, - 0x8E, - 0xC, - 0x32, - 0x90, - 0xF0, - 0x1F, - 0x20, - 0x49, - 0xE0, - 0xF8, - 0xC, - 0x60, - 0xF0 - //220 - , - 0x17, - 0x1A, - 0x41, - 0xAA, - 0xA4, - 0xD0, - 0x8D, - 0x12, - 0x82, - 0x1E, - 0x1E, - 3, - 0xF8, - 0x3E, - 3, - 0xC, - 0x73, - 0x80, - 0x70, - 0x44, - 0x26, - 3, - 0x24, - 0xE1, - 0x3E, - 4, - 0x4E, - 4, - 0x1C, - 0xC1, - 9, - 0xCC - //240 - , - 0x9E, - 0x90, - 0x21, - 7, - 0x90, - 0x43, - 0x64, - 0xC0, - 0xF, - 0xC6, - 0x90, - 0x9C, - 0xC1, - 0x5B, - 3, - 0xE2, - 0x1D, - 0x81, - 0xE0, - 0x5E, - 0x1D, - 3, - 0x84, - 0xB8, - 0x2C, - 0xF, - 0x80, - 0xB1, - 0x83, - 0xE0, - 0x30, - 0x41 - //260 - , - 0x1E, - 0x43, - 0x89, - 0x83, - 0x50, - 0xFC, - 0x24, - 0x2E, - 0x13, - 0x83, - 0xF1, - 0x7C, - 0x4C, - 0x2C, - 0xC9, - 0xD, - 0x83, - 0xB0, - 0xB5, - 0x82, - 0xE4, - 0xE8, - 6, - 0x9C, - 7, - 0xA0, - 0x99, - 0x1D, - 7, - 0x3E, - 0x82, - 0x8F - //280 - , - 0x70, - 0x30, - 0x74, - 0x40, - 0xCA, - 0x10, - 0xE4, - 0xE8, - 0xF, - 0x92, - 0x14, - 0x3F, - 6, - 0xF8, - 0x84, - 0x88, - 0x43, - 0x81, - 0xA, - 0x34, - 0x39, - 0x41, - 0xC6, - 0xE3, - 0x1C, - 0x47, - 3, - 0xB0, - 0xB8, - 0x13, - 0xA, - 0xC2 - //2A0 - , - 0x64, - 0xF8, - 0x18, - 0xF9, - 0x60, - 0xB3, - 0xC0, - 0x65, - 0x20, - 0x60, - 0xA6, - 0x8C, - 0xC3, - 0x81, - 0x20, - 0x30, - 0x26, - 0x1E, - 0x1C, - 0x38, - 0xD3, - 1, - 0xB0, - 0x26, - 0x40, - 0xF4, - 0xB, - 0xC3, - 0x42, - 0x1F, - 0x85, - 0x32 - //2C0 - , - 0x26, - 0x60, - 0x40, - 0xC9, - 0xCB, - 1, - 0xEC, - 0x11, - 0x28, - 0x40, - 0xFA, - 4, - 0x34, - 0xE0, - 0x70, - 0x4C, - 0x8C, - 0x1D, - 7, - 0x69, - 3, - 0x16, - 0xC8, - 4, - 0x23, - 0xE8, - 0xC6, - 0x9A, - 0xB, - 0x1A, - 3, - 0xE0 - //2E0 - , - 0x76, - 6, - 5, - 0xCF, - 0x1E, - 0xBC, - 0x58, - 0x31, - 0x71, - 0x66, - 0, - 0xF8, - 0x3F, - 4, - 0xFC, - 0xC, - 0x74, - 0x27, - 0x8A, - 0x80, - 0x71, - 0xC2, - 0x3A, - 0x26, - 6, - 0xC0, - 0x1F, - 5, - 0xF, - 0x98, - 0x40, - 0xAE - //300 - , - 1, - 0x7F, - 0xC0, - 7, - 0xFF, - 0, - 0xE, - 0xFE, - 0, - 3, - 0xDF, - 0x80, - 3, - 0xEF, - 0x80, - 0x1B, - 0xF1, - 0xC2, - 0, - 0xE7, - 0xE0, - 0x18, - 0xFC, - 0xE0, - 0x21, - 0xFC, - 0x80, - 0x3C, - 0xFC, - 0x40, - 0xE, - 0x7E - //320 - , - 0, - 0x3F, - 0x3E, - 0, - 0xF, - 0xFE, - 0, - 0x1F, - 0xFF, - 0, - 0x3E, - 0xF0, - 7, - 0xFC, - 0, - 0x7E, - 0x10, - 0x3F, - 0xFF, - 0, - 0x3F, - 0x38, - 0xE, - 0x7C, - 1, - 0x87, - 0xC, - 0xFC, - 0xC7, - 0, - 0x3E, - 4 - //340 - , - 0xF, - 0x3E, - 0x1F, - 0xF, - 0xF, - 0x1F, - 0xF, - 2, - 0x83, - 0x87, - 0xCF, - 3, - 0x87, - 0xF, - 0x3F, - 0xC0, - 7, - 0x9E, - 0x60, - 0x3F, - 0xC0, - 3, - 0xFE, - 0, - 0x3F, - 0xE0, - 0x77, - 0xE1, - 0xC0, - 0xFE, - 0xE0, - 0xC3 - //360 - , - 0xE0, - 1, - 0xDF, - 0xF8, - 3, - 7, - 0, - 0x7E, - 0x70, - 0, - 0x7C, - 0x38, - 0x18, - 0xFE, - 0xC, - 0x1E, - 0x78, - 0x1C, - 0x7C, - 0x3E, - 0xE, - 0x1F, - 0x1E, - 0x1E, - 0x3E, - 0, - 0x7F, - 0x83, - 7, - 0xDB, - 0x87, - 0x83 - //380 - , - 7, - 0xC7, - 7, - 0x10, - 0x71, - 0xFF, - 0, - 0x3F, - 0xE2, - 1, - 0xE0, - 0xC1, - 0xC3, - 0xE1, - 0, - 0x7F, - 0xC0, - 5, - 0xF0, - 0x20, - 0xF8, - 0xF0, - 0x70, - 0xFE, - 0x78, - 0x79, - 0xF8, - 2, - 0x3F, - 0xC, - 0x8F, - 3 - //3a0 - , - 0xF, - 0x9F, - 0xE0, - 0xC1, - 0xC7, - 0x87, - 3, - 0xC3, - 0xC3, - 0xB0, - 0xE1, - 0xE1, - 0xC1, - 0xE3, - 0xE0, - 0x71, - 0xF0, - 0, - 0xFC, - 0x70, - 0x7C, - 0xC, - 0x3E, - 0x38, - 0xE, - 0x1C, - 0x70, - 0xC3, - 0xC7, - 3, - 0x81, - 0xC1 - //3c0 - , - 0xC7, - 0xE7, - 0, - 0xF, - 0xC7, - 0x87, - 0x19, - 9, - 0xEF, - 0xC4, - 0x33, - 0xE0, - 0xC1, - 0xFC, - 0xF8, - 0x70, - 0xF0, - 0x78, - 0xF8, - 0xF0, - 0x61, - 0xC7, - 0, - 0x1F, - 0xF8, - 1, - 0x7C, - 0xF8, - 0xF0, - 0x78, - 0x70, - 0x3C - //3e0 - , - 0x7C, - 0xCE, - 0xE, - 0x21, - 0x83, - 0xCF, - 8, - 7, - 0x8F, - 8, - 0xC1, - 0x87, - 0x8F, - 0x80, - 0xC7, - 0xE3, - 0, - 7, - 0xF8, - 0xE0, - 0xEF, - 0, - 0x39, - 0xF7, - 0x80, - 0xE, - 0xF8, - 0xE1, - 0xE3, - 0xF8, - 0x21, - 0x9F - //400 - , - 0xC0, - 0xFF, - 3, - 0xF8, - 7, - 0xC0, - 0x1F, - 0xF8, - 0xC4, - 4, - 0xFC, - 0xC4, - 0xC1, - 0xBC, - 0x87, - 0xF0, - 0xF, - 0xC0, - 0x7F, - 5, - 0xE0, - 0x25, - 0xEC, - 0xC0, - 0x3E, - 0x84, - 0x47, - 0xF0, - 0x8E, - 3, - 0xF8, - 3 - //420 - , - 0xFB, - 0xC0, - 0x19, - 0xF8, - 7, - 0x9C, - 0xC, - 0x17, - 0xF8, - 7, - 0xE0, - 0x1F, - 0xA1, - 0xFC, - 0xF, - 0xFC, - 1, - 0xF0, - 0x3F, - 0, - 0xFE, - 3, - 0xF0, - 0x1F, - 0, - 0xFD, - 0, - 0xFF, - 0x88, - 0xD, - 0xF9, - 1 - //440 - , - 0xFF, - 0, - 0x70, - 7, - 0xC0, - 0x3E, - 0x42, - 0xF3, - 0xD, - 0xC4, - 0x7F, - 0x80, - 0xFC, - 7, - 0xF0, - 0x5E, - 0xC0, - 0x3F, - 0, - 0x78, - 0x3F, - 0x81, - 0xFF, - 1, - 0xF8, - 1, - 0xC3, - 0xE8, - 0xC, - 0xE4, - 0x64, - 0x8F - ////460 - , - 0xE4, - 0xF, - 0xF0, - 7, - 0xF0, - 0xC2, - 0x1F, - 0, - 0x7F, - 0xC0, - 0x6F, - 0x80, - 0x7E, - 3, - 0xF8, - 7, - 0xF0, - 0x3F, - 0xC0, - 0x78, - 0xF, - 0x82, - 7, - 0xFE, - 0x22, - 0x77, - 0x70, - 2, - 0x76, - 3, - 0xFE, - 0 - //480 - , - 0xFE, - 0x67, - 0, - 0x7C, - 0xC7, - 0xF1, - 0x8E, - 0xC6, - 0x3B, - 0xE0, - 0x3F, - 0x84, - 0xF3, - 0x19, - 0xD8, - 3, - 0x99, - 0xFC, - 9, - 0xB8, - 0xF, - 0xF8, - 0, - 0x9D, - 0x24, - 0x61, - 0xF9, - 0xD, - 0, - 0xFD, - 3, - 0xF0 - //4a0 - , - 0x1F, - 0x90, - 0x3F, - 1, - 0xF8, - 0x1F, - 0xD0, - 0xF, - 0xF8, - 0x37, - 1, - 0xF8, - 7, - 0xF0, - 0xF, - 0xC0, - 0x3F, - 0, - 0xFE, - 3, - 0xF8, - 0xF, - 0xC0, - 0x3F, - 0, - 0xFA, - 3, - 0xF0, - 0xF, - 0x80, - 0xFF, - 1 - //4c0 - , - 0xB8, - 7, - 0xF0, - 1, - 0xFC, - 1, - 0xBC, - 0x80, - 0x13, - 0x1E, - 0, - 0x7F, - 0xE1, - 0x40, - 0x7F, - 0xA0, - 0x7F, - 0xB0, - 0, - 0x3F, - 0xC0, - 0x1F, - 0xC0, - 0x38, - 0xF, - 0xF0, - 0x1F, - 0x80, - 0xFF, - 1, - 0xFC, - 3 - //4e0 - , - 0xF1, - 0x7E, - 1, - 0xFE, - 1, - 0xF0, - 0xFF, - 0, - 0x7F, - 0xC0, - 0x1D, - 7, - 0xF0, - 0xF, - 0xC0, - 0x7E, - 6, - 0xE0, - 7, - 0xE0, - 0xF, - 0xF8, - 6, - 0xC1, - 0xFE, - 1, - 0xFC, - 3, - 0xE0, - 0xF, - 0, - 0xFC}; - -//////////////////////////////////////////////////////////////////////////////////////////// -// -// Render -// -//////////////////////////////////////////////////////////////////////////////////////////// - -unsigned char pitches[256]; // tab43008 - -unsigned char frequency1[256]; -unsigned char frequency2[256]; -unsigned char frequency3[256]; - -unsigned char amplitude1[256]; -unsigned char amplitude2[256]; -unsigned char amplitude3[256]; - -unsigned char sampledConsonantFlag[256]; // tab44800 - -//////////////////////////////////////////////////////////////////////////////////////////// -// -// Sam -// -//////////////////////////////////////////////////////////////////////////////////////////// - -unsigned char stress[256]; //numbers from 0 to 8 -unsigned char phonemeLength[256]; //tab40160 -unsigned char phonemeindex[256]; - -//////////////////////////////////////////////////////////////////////////////////////////// -// -// ReciterTabs -// -//////////////////////////////////////////////////////////////////////////////////////////// - -//some flags -const unsigned char tab36376[] = { - 0, 0, 0, 0, 0, 0, 0, 0, // 0-7 - 0, 0, 0, 0, 0, 0, 0, 0, // 8-15 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2, 2, 2, 2, 2, 2, 130, // ' ', '!' - 0, 0, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 2, 2, 2, 2, 2, 2, 2, 192, 168, 176, 172, 192, 160, 184, // '@', 'A' - 160, 192, 188, 160, 172, 168, 172, 192, 160, 160, 172, 180, 164, 192, 168, 168, - 176, 192, 188, 0, 0, 0, 2, 0, // 'X', 'Y', 'Z', '[', - 32, 32, 155, 32, 192, 185, 32, 205, 163, 76, 138, 142}; - -const unsigned char rules[] = { - ']', 'A' | 0x80, ' ', '(', 'A', '.', ')', '=', - 'E', 'H', '4', 'Y', '.', ' ' | 0x80, '(', 'A', - ')', ' ', '=', 'A', 'H' | 0x80, ' ', '(', 'A', - 'R', 'E', ')', ' ', '=', 'A', 'A', 'R' | 0x80, - ' ', '(', 'A', 'R', ')', 'O', '=', 'A', - 'X', 'R' | 0x80, '(', 'A', 'R', ')', '#', '=', - 'E', 'H', '4', 'R' | 0x80, ' ', '^', '(', 'A', - 'S', ')', '#', '=', 'E', 'Y', '4', 'S' | 0x80, - '(', 'A', ')', 'W', 'A', '=', 'A', 'X' | 0x80, - '(', 'A', 'W', ')', '=', 'A', 'O', '5' | 0x80, - ' ', ':', '(', 'A', 'N', 'Y', ')', '=', - 'E', 'H', '4', 'N', 'I', 'Y' | 0x80, '(', 'A', - ')', '^', '+', '#', '=', 'E', 'Y', '5' | 0x80, - '#', ':', '(', 'A', 'L', 'L', 'Y', ')', - '=', 'U', 'L', 'I', 'Y' | 0x80, ' ', '(', 'A', - 'L', ')', '#', '=', 'U', 'L' | 0x80, '(', 'A', - 'G', 'A', 'I', 'N', ')', '=', 'A', 'X', - 'G', 'E', 'H', '4', 'N' | 0x80, '#', ':', '(', - 'A', 'G', ')', 'E', '=', 'I', 'H', 'J' | 0x80, - '(', 'A', ')', '^', '%', '=', 'E', 'Y' | 0x80, - '(', 'A', ')', '^', '+', ':', '#', '=', - 'A', 'E' | 0x80, ' ', ':', '(', 'A', ')', '^', - '+', ' ', '=', 'E', 'Y', '4' | 0x80, ' ', '(', - 'A', 'R', 'R', ')', '=', 'A', 'X', 'R' | 0x80, - '(', 'A', 'R', 'R', ')', '=', 'A', 'E', - '4', 'R' | 0x80, ' ', '^', '(', 'A', 'R', ')', - ' ', '=', 'A', 'A', '5', 'R' | 0x80, '(', 'A', - 'R', ')', '=', 'A', 'A', '5', 'R' | 0x80, '(', - 'A', 'I', 'R', ')', '=', 'E', 'H', '4', - 'R' | 0x80, '(', 'A', 'I', ')', '=', 'E', 'Y', - '4' | 0x80, '(', 'A', 'Y', ')', '=', 'E', 'Y', - '5' | 0x80, '(', 'A', 'U', ')', '=', 'A', 'O', - '4' | 0x80, '#', ':', '(', 'A', 'L', ')', ' ', - '=', 'U', 'L' | 0x80, '#', ':', '(', 'A', 'L', - 'S', ')', ' ', '=', 'U', 'L', 'Z' | 0x80, '(', - 'A', 'L', 'K', ')', '=', 'A', 'O', '4', - 'K' | 0x80, '(', 'A', 'L', ')', '^', '=', 'A', - 'O', 'L' | 0x80, ' ', ':', '(', 'A', 'B', 'L', - 'E', ')', '=', 'E', 'Y', '4', 'B', 'U', - 'L' | 0x80, '(', 'A', 'B', 'L', 'E', ')', '=', - 'A', 'X', 'B', 'U', 'L' | 0x80, '(', 'A', ')', - 'V', 'O', '=', 'E', 'Y', '4' | 0x80, '(', 'A', - 'N', 'G', ')', '+', '=', 'E', 'Y', '4', - 'N', 'J' | 0x80, '(', 'A', 'T', 'A', 'R', 'I', - ')', '=', 'A', 'H', 'T', 'A', 'A', '4', - 'R', 'I', 'Y' | 0x80, '(', 'A', ')', 'T', 'O', - 'M', '=', 'A', 'E' | 0x80, '(', 'A', ')', 'T', - 'T', 'I', '=', 'A', 'E' | 0x80, ' ', '(', 'A', - 'T', ')', ' ', '=', 'A', 'E', 'T' | 0x80, ' ', - '(', 'A', ')', 'T', '=', 'A', 'H' | 0x80, '(', - 'A', ')', '=', 'A', 'E' | 0x80, - - ']', 'B' | 0x80, ' ', '(', 'B', ')', ' ', '=', - 'B', 'I', 'Y', '4' | 0x80, ' ', '(', 'B', 'E', - ')', '^', '#', '=', 'B', 'I', 'H' | 0x80, '(', - 'B', 'E', 'I', 'N', 'G', ')', '=', 'B', - 'I', 'Y', '4', 'I', 'H', 'N', 'X' | 0x80, ' ', - '(', 'B', 'O', 'T', 'H', ')', ' ', '=', - 'B', 'O', 'W', '4', 'T', 'H' | 0x80, ' ', '(', - 'B', 'U', 'S', ')', '#', '=', 'B', 'I', - 'H', '4', 'Z' | 0x80, '(', 'B', 'R', 'E', 'A', - 'K', ')', '=', 'B', 'R', 'E', 'Y', '5', - 'K' | 0x80, '(', 'B', 'U', 'I', 'L', ')', '=', - 'B', 'I', 'H', '4', 'L' | 0x80, '(', 'B', ')', - '=', 'B' | 0x80, - - ']', 'C' | 0x80, ' ', '(', 'C', ')', ' ', '=', - 'S', 'I', 'Y', '4' | 0x80, ' ', '(', 'C', 'H', - ')', '^', '=', 'K' | 0x80, '^', 'E', '(', 'C', - 'H', ')', '=', 'K' | 0x80, '(', 'C', 'H', 'A', - ')', 'R', '#', '=', 'K', 'E', 'H', '5' | 0x80, - '(', 'C', 'H', ')', '=', 'C', 'H' | 0x80, ' ', - 'S', '(', 'C', 'I', ')', '#', '=', 'S', - 'A', 'Y', '4' | 0x80, '(', 'C', 'I', ')', 'A', - '=', 'S', 'H' | 0x80, '(', 'C', 'I', ')', 'O', - '=', 'S', 'H' | 0x80, '(', 'C', 'I', ')', 'E', - 'N', '=', 'S', 'H' | 0x80, '(', 'C', 'I', 'T', - 'Y', ')', '=', 'S', 'I', 'H', 'T', 'I', - 'Y' | 0x80, '(', 'C', ')', '+', '=', 'S' | 0x80, '(', - 'C', 'K', ')', '=', 'K' | 0x80, '(', 'C', 'O', - 'M', 'M', 'O', 'D', 'O', 'R', 'E', ')', - '=', 'K', 'A', 'A', '4', 'M', 'A', 'H', - 'D', 'O', 'H', 'R' | 0x80, '(', 'C', 'O', 'M', - ')', '=', 'K', 'A', 'H', 'M' | 0x80, '(', 'C', - 'U', 'I', 'T', ')', '=', 'K', 'I', 'H', - 'T' | 0x80, '(', 'C', 'R', 'E', 'A', ')', '=', - 'K', 'R', 'I', 'Y', 'E', 'Y' | 0x80, '(', 'C', - ')', '=', 'K' | 0x80, - - ']', 'D' | 0x80, ' ', '(', 'D', ')', ' ', '=', - 'D', 'I', 'Y', '4' | 0x80, ' ', '(', 'D', 'R', - '.', ')', ' ', '=', 'D', 'A', 'A', '4', - 'K', 'T', 'E', 'R' | 0x80, '#', ':', '(', 'D', - 'E', 'D', ')', ' ', '=', 'D', 'I', 'H', - 'D' | 0x80, '.', 'E', '(', 'D', ')', ' ', '=', - 'D' | 0x80, '#', ':', '^', 'E', '(', 'D', ')', - ' ', '=', 'T' | 0x80, ' ', '(', 'D', 'E', ')', - '^', '#', '=', 'D', 'I', 'H' | 0x80, ' ', '(', - 'D', 'O', ')', ' ', '=', 'D', 'U', 'W' | 0x80, - ' ', '(', 'D', 'O', 'E', 'S', ')', '=', - 'D', 'A', 'H', 'Z' | 0x80, '(', 'D', 'O', 'N', - 'E', ')', ' ', '=', 'D', 'A', 'H', '5', - 'N' | 0x80, '(', 'D', 'O', 'I', 'N', 'G', ')', - '=', 'D', 'U', 'W', '4', 'I', 'H', 'N', - 'X' | 0x80, ' ', '(', 'D', 'O', 'W', ')', '=', - 'D', 'A', 'W' | 0x80, '#', '(', 'D', 'U', ')', - 'A', '=', 'J', 'U', 'W' | 0x80, '#', '(', 'D', - 'U', ')', '^', '#', '=', 'J', 'A', 'X' | 0x80, - '(', 'D', ')', '=', 'D' | 0x80, - - ']', 'E' | 0x80, ' ', '(', 'E', ')', ' ', '=', - 'I', 'Y', 'I', 'Y', '4' | 0x80, '#', ':', '(', - 'E', ')', ' ', '=' | 0x80, '\'', ':', '^', '(', - 'E', ')', ' ', '=' | 0x80, ' ', ':', '(', 'E', - ')', ' ', '=', 'I', 'Y' | 0x80, '#', '(', 'E', - 'D', ')', ' ', '=', 'D' | 0x80, '#', ':', '(', - 'E', ')', 'D', ' ', '=' | 0x80, '(', 'E', 'V', - ')', 'E', 'R', '=', 'E', 'H', '4', 'V' | 0x80, - '(', 'E', ')', '^', '%', '=', 'I', 'Y', - '4' | 0x80, '(', 'E', 'R', 'I', ')', '#', '=', - 'I', 'Y', '4', 'R', 'I', 'Y' | 0x80, '(', 'E', - 'R', 'I', ')', '=', 'E', 'H', '4', 'R', - 'I', 'H' | 0x80, '#', ':', '(', 'E', 'R', ')', - '#', '=', 'E', 'R' | 0x80, '(', 'E', 'R', 'R', - 'O', 'R', ')', '=', 'E', 'H', '4', 'R', - 'O', 'H', 'R' | 0x80, '(', 'E', 'R', 'A', 'S', - 'E', ')', '=', 'I', 'H', 'R', 'E', 'Y', - '5', 'S' | 0x80, '(', 'E', 'R', ')', '#', '=', - 'E', 'H', 'R' | 0x80, '(', 'E', 'R', ')', '=', - 'E', 'R' | 0x80, ' ', '(', 'E', 'V', 'E', 'N', - ')', '=', 'I', 'Y', 'V', 'E', 'H', 'N' | 0x80, - '#', ':', '(', 'E', ')', 'W', '=' | 0x80, '@', - '(', 'E', 'W', ')', '=', 'U', 'W' | 0x80, '(', - 'E', 'W', ')', '=', 'Y', 'U', 'W' | 0x80, '(', - 'E', ')', 'O', '=', 'I', 'Y' | 0x80, '#', ':', - '&', '(', 'E', 'S', ')', ' ', '=', 'I', - 'H', 'Z' | 0x80, '#', ':', '(', 'E', ')', 'S', - ' ', '=' | 0x80, '#', ':', '(', 'E', 'L', 'Y', - ')', ' ', '=', 'L', 'I', 'Y' | 0x80, '#', ':', - '(', 'E', 'M', 'E', 'N', 'T', ')', '=', - 'M', 'E', 'H', 'N', 'T' | 0x80, '(', 'E', 'F', - 'U', 'L', ')', '=', 'F', 'U', 'H', 'L' | 0x80, - '(', 'E', 'E', ')', '=', 'I', 'Y', '4' | 0x80, - '(', 'E', 'A', 'R', 'N', ')', '=', 'E', - 'R', '5', 'N' | 0x80, ' ', '(', 'E', 'A', 'R', - ')', '^', '=', 'E', 'R', '5' | 0x80, '(', 'E', - 'A', 'D', ')', '=', 'E', 'H', 'D' | 0x80, '#', - ':', '(', 'E', 'A', ')', ' ', '=', 'I', - 'Y', 'A', 'X' | 0x80, '(', 'E', 'A', ')', 'S', - 'U', '=', 'E', 'H', '5' | 0x80, '(', 'E', 'A', - ')', '=', 'I', 'Y', '5' | 0x80, '(', 'E', 'I', - 'G', 'H', ')', '=', 'E', 'Y', '4' | 0x80, '(', - 'E', 'I', ')', '=', 'I', 'Y', '4' | 0x80, ' ', - '(', 'E', 'Y', 'E', ')', '=', 'A', 'Y', - '4' | 0x80, '(', 'E', 'Y', ')', '=', 'I', 'Y' | 0x80, - '(', 'E', 'U', ')', '=', 'Y', 'U', 'W', - '5' | 0x80, '(', 'E', 'Q', 'U', 'A', 'L', ')', - '=', 'I', 'Y', '4', 'K', 'W', 'U', 'L' | 0x80, - '(', 'E', ')', '=', 'E', 'H' | 0x80, - - ']', 'F' | 0x80, ' ', '(', 'F', ')', ' ', '=', - 'E', 'H', '4', 'F' | 0x80, '(', 'F', 'U', 'L', - ')', '=', 'F', 'U', 'H', 'L' | 0x80, '(', 'F', - 'R', 'I', 'E', 'N', 'D', ')', '=', 'F', - 'R', 'E', 'H', '5', 'N', 'D' | 0x80, '(', 'F', - 'A', 'T', 'H', 'E', 'R', ')', '=', 'F', - 'A', 'A', '4', 'D', 'H', 'E', 'R' | 0x80, '(', - 'F', ')', 'F', '=' | 0x80, '(', 'F', ')', '=', - 'F' | 0x80, - - ']', 'G' | 0x80, ' ', '(', 'G', ')', ' ', '=', - 'J', 'I', 'Y', '4' | 0x80, '(', 'G', 'I', 'V', - ')', '=', 'G', 'I', 'H', '5', 'V' | 0x80, ' ', - '(', 'G', ')', 'I', '^', '=', 'G' | 0x80, '(', - 'G', 'E', ')', 'T', '=', 'G', 'E', 'H', - '5' | 0x80, 'S', 'U', '(', 'G', 'G', 'E', 'S', - ')', '=', 'G', 'J', 'E', 'H', '4', 'S' | 0x80, - '(', 'G', 'G', ')', '=', 'G' | 0x80, ' ', 'B', - '#', '(', 'G', ')', '=', 'G' | 0x80, '(', 'G', - ')', '+', '=', 'J' | 0x80, '(', 'G', 'R', 'E', - 'A', 'T', ')', '=', 'G', 'R', 'E', 'Y', - '4', 'T' | 0x80, '(', 'G', 'O', 'N', ')', 'E', - '=', 'G', 'A', 'O', '5', 'N' | 0x80, '#', '(', - 'G', 'H', ')', '=' | 0x80, ' ', '(', 'G', 'N', - ')', '=', 'N' | 0x80, '(', 'G', ')', '=', 'G' | 0x80, - - ']', 'H' | 0x80, ' ', '(', 'H', ')', ' ', '=', - 'E', 'Y', '4', 'C', 'H' | 0x80, ' ', '(', 'H', - 'A', 'V', ')', '=', '/', 'H', 'A', 'E', - '6', 'V' | 0x80, ' ', '(', 'H', 'E', 'R', 'E', - ')', '=', '/', 'H', 'I', 'Y', 'R' | 0x80, ' ', - '(', 'H', 'O', 'U', 'R', ')', '=', 'A', - 'W', '5', 'E', 'R' | 0x80, '(', 'H', 'O', 'W', - ')', '=', '/', 'H', 'A', 'W' | 0x80, '(', 'H', - ')', '#', '=', '/', 'H' | 0x80, '(', 'H', ')', - '=' | 0x80, - - ']', 'I' | 0x80, ' ', '(', 'I', 'N', ')', '=', - 'I', 'H', 'N' | 0x80, ' ', '(', 'I', ')', ' ', - '=', 'A', 'Y', '4' | 0x80, '(', 'I', ')', ' ', - '=', 'A', 'Y' | 0x80, '(', 'I', 'N', ')', 'D', - '=', 'A', 'Y', '5', 'N' | 0x80, 'S', 'E', 'M', - '(', 'I', ')', '=', 'I', 'Y' | 0x80, ' ', 'A', - 'N', 'T', '(', 'I', ')', '=', 'A', 'Y' | 0x80, - '(', 'I', 'E', 'R', ')', '=', 'I', 'Y', - 'E', 'R' | 0x80, '#', ':', 'R', '(', 'I', 'E', - 'D', ')', ' ', '=', 'I', 'Y', 'D' | 0x80, '(', - 'I', 'E', 'D', ')', ' ', '=', 'A', 'Y', - '5', 'D' | 0x80, '(', 'I', 'E', 'N', ')', '=', - 'I', 'Y', 'E', 'H', 'N' | 0x80, '(', 'I', 'E', - ')', 'T', '=', 'A', 'Y', '4', 'E', 'H' | 0x80, - '(', 'I', '\'', ')', '=', 'A', 'Y', '5' | 0x80, - ' ', ':', '(', 'I', ')', '^', '%', '=', - 'A', 'Y', '5' | 0x80, ' ', ':', '(', 'I', 'E', - ')', ' ', '=', 'A', 'Y', '4' | 0x80, '(', 'I', - ')', '%', '=', 'I', 'Y' | 0x80, '(', 'I', 'E', - ')', '=', 'I', 'Y', '4' | 0x80, ' ', '(', 'I', - 'D', 'E', 'A', ')', '=', 'A', 'Y', 'D', - 'I', 'Y', '5', 'A', 'H' | 0x80, '(', 'I', ')', - '^', '+', ':', '#', '=', 'I', 'H' | 0x80, '(', - 'I', 'R', ')', '#', '=', 'A', 'Y', 'R' | 0x80, - '(', 'I', 'Z', ')', '%', '=', 'A', 'Y', - 'Z' | 0x80, '(', 'I', 'S', ')', '%', '=', 'A', - 'Y', 'Z' | 0x80, 'I', '^', '(', 'I', ')', '^', - '#', '=', 'I', 'H' | 0x80, '+', '^', '(', 'I', - ')', '^', '+', '=', 'A', 'Y' | 0x80, '#', ':', - '^', '(', 'I', ')', '^', '+', '=', 'I', - 'H' | 0x80, '(', 'I', ')', '^', '+', '=', 'A', - 'Y' | 0x80, '(', 'I', 'R', ')', '=', 'E', 'R' | 0x80, - '(', 'I', 'G', 'H', ')', '=', 'A', 'Y', - '4' | 0x80, '(', 'I', 'L', 'D', ')', '=', 'A', - 'Y', '5', 'L', 'D' | 0x80, ' ', '(', 'I', 'G', - 'N', ')', '=', 'I', 'H', 'G', 'N' | 0x80, '(', - 'I', 'G', 'N', ')', ' ', '=', 'A', 'Y', - '4', 'N' | 0x80, '(', 'I', 'G', 'N', ')', '^', - '=', 'A', 'Y', '4', 'N' | 0x80, '(', 'I', 'G', - 'N', ')', '%', '=', 'A', 'Y', '4', 'N' | 0x80, - '(', 'I', 'C', 'R', 'O', ')', '=', 'A', - 'Y', '4', 'K', 'R', 'O', 'H' | 0x80, '(', 'I', - 'Q', 'U', 'E', ')', '=', 'I', 'Y', '4', - 'K' | 0x80, '(', 'I', ')', '=', 'I', 'H' | 0x80, - - ']', 'J' | 0x80, ' ', '(', 'J', ')', ' ', '=', - 'J', 'E', 'Y', '4' | 0x80, '(', 'J', ')', '=', - 'J' | 0x80, - - ']', 'K' | 0x80, ' ', '(', 'K', ')', ' ', '=', - 'K', 'E', 'Y', '4' | 0x80, ' ', '(', 'K', ')', - 'N', '=' | 0x80, '(', 'K', ')', '=', 'K' | 0x80, - - ']', 'L' | 0x80, ' ', '(', 'L', ')', ' ', '=', - 'E', 'H', '4', 'L' | 0x80, '(', 'L', 'O', ')', - 'C', '#', '=', 'L', 'O', 'W' | 0x80, 'L', '(', - 'L', ')', '=' | 0x80, '#', ':', '^', '(', 'L', - ')', '%', '=', 'U', 'L' | 0x80, '(', 'L', 'E', - 'A', 'D', ')', '=', 'L', 'I', 'Y', 'D' | 0x80, - ' ', '(', 'L', 'A', 'U', 'G', 'H', ')', - '=', 'L', 'A', 'E', '4', 'F' | 0x80, '(', 'L', - ')', '=', 'L' | 0x80, - - ']', 'M' | 0x80, ' ', '(', 'M', ')', ' ', '=', - 'E', 'H', '4', 'M' | 0x80, ' ', '(', 'M', 'R', - '.', ')', ' ', '=', 'M', 'I', 'H', '4', - 'S', 'T', 'E', 'R' | 0x80, ' ', '(', 'M', 'S', - '.', ')', '=', 'M', 'I', 'H', '5', 'Z' | 0x80, - ' ', '(', 'M', 'R', 'S', '.', ')', ' ', - '=', 'M', 'I', 'H', '4', 'S', 'I', 'X', - 'Z' | 0x80, '(', 'M', 'O', 'V', ')', '=', 'M', - 'U', 'W', '4', 'V' | 0x80, '(', 'M', 'A', 'C', - 'H', 'I', 'N', ')', '=', 'M', 'A', 'H', - 'S', 'H', 'I', 'Y', '5', 'N' | 0x80, 'M', '(', - 'M', ')', '=' | 0x80, '(', 'M', ')', '=', 'M' | 0x80, - - ']', 'N' | 0x80, ' ', '(', 'N', ')', ' ', '=', - 'E', 'H', '4', 'N' | 0x80, 'E', '(', 'N', 'G', - ')', '+', '=', 'N', 'J' | 0x80, '(', 'N', 'G', - ')', 'R', '=', 'N', 'X', 'G' | 0x80, '(', 'N', - 'G', ')', '#', '=', 'N', 'X', 'G' | 0x80, '(', - 'N', 'G', 'L', ')', '%', '=', 'N', 'X', - 'G', 'U', 'L' | 0x80, '(', 'N', 'G', ')', '=', - 'N', 'X' | 0x80, '(', 'N', 'K', ')', '=', 'N', - 'X', 'K' | 0x80, ' ', '(', 'N', 'O', 'W', ')', - ' ', '=', 'N', 'A', 'W', '4' | 0x80, 'N', '(', - 'N', ')', '=' | 0x80, '(', 'N', 'O', 'N', ')', - 'E', '=', 'N', 'A', 'H', '4', 'N' | 0x80, '(', - 'N', ')', '=', 'N' | 0x80, - - ']', 'O' | 0x80, ' ', '(', 'O', ')', ' ', '=', - 'O', 'H', '4', 'W' | 0x80, '(', 'O', 'F', ')', - ' ', '=', 'A', 'H', 'V' | 0x80, ' ', '(', 'O', - 'H', ')', ' ', '=', 'O', 'W', '5' | 0x80, '(', - 'O', 'R', 'O', 'U', 'G', 'H', ')', '=', - 'E', 'R', '4', 'O', 'W' | 0x80, '#', ':', '(', - 'O', 'R', ')', ' ', '=', 'E', 'R' | 0x80, '#', - ':', '(', 'O', 'R', 'S', ')', ' ', '=', - 'E', 'R', 'Z' | 0x80, '(', 'O', 'R', ')', '=', - 'A', 'O', 'R' | 0x80, ' ', '(', 'O', 'N', 'E', - ')', '=', 'W', 'A', 'H', 'N' | 0x80, '#', '(', - 'O', 'N', 'E', ')', ' ', '=', 'W', 'A', - 'H', 'N' | 0x80, '(', 'O', 'W', ')', '=', 'O', - 'W' | 0x80, ' ', '(', 'O', 'V', 'E', 'R', ')', - '=', 'O', 'W', '5', 'V', 'E', 'R' | 0x80, 'P', - 'R', '(', 'O', ')', 'V', '=', 'U', 'W', - '4' | 0x80, '(', 'O', 'V', ')', '=', 'A', 'H', - '4', 'V' | 0x80, '(', 'O', ')', '^', '%', '=', - 'O', 'W', '5' | 0x80, '(', 'O', ')', '^', 'E', - 'N', '=', 'O', 'W' | 0x80, '(', 'O', ')', '^', - 'I', '#', '=', 'O', 'W', '5' | 0x80, '(', 'O', - 'L', ')', 'D', '=', 'O', 'W', '4', 'L' | 0x80, - '(', 'O', 'U', 'G', 'H', 'T', ')', '=', - 'A', 'O', '5', 'T' | 0x80, '(', 'O', 'U', 'G', - 'H', ')', '=', 'A', 'H', '5', 'F' | 0x80, ' ', - '(', 'O', 'U', ')', '=', 'A', 'W' | 0x80, 'H', - '(', 'O', 'U', ')', 'S', '#', '=', 'A', - 'W', '4' | 0x80, '(', 'O', 'U', 'S', ')', '=', - 'A', 'X', 'S' | 0x80, '(', 'O', 'U', 'R', ')', - '=', 'O', 'H', 'R' | 0x80, '(', 'O', 'U', 'L', - 'D', ')', '=', 'U', 'H', '5', 'D' | 0x80, '(', - 'O', 'U', ')', '^', 'L', '=', 'A', 'H', - '5' | 0x80, '(', 'O', 'U', 'P', ')', '=', 'U', - 'W', '5', 'P' | 0x80, '(', 'O', 'U', ')', '=', - 'A', 'W' | 0x80, '(', 'O', 'Y', ')', '=', 'O', - 'Y' | 0x80, '(', 'O', 'I', 'N', 'G', ')', '=', - 'O', 'W', '4', 'I', 'H', 'N', 'X' | 0x80, '(', - 'O', 'I', ')', '=', 'O', 'Y', '5' | 0x80, '(', - 'O', 'O', 'R', ')', '=', 'O', 'H', '5', - 'R' | 0x80, '(', 'O', 'O', 'K', ')', '=', 'U', - 'H', '5', 'K' | 0x80, 'F', '(', 'O', 'O', 'D', - ')', '=', 'U', 'W', '5', 'D' | 0x80, 'L', '(', - 'O', 'O', 'D', ')', '=', 'A', 'H', '5', - 'D' | 0x80, 'M', '(', 'O', 'O', 'D', ')', '=', - 'U', 'W', '5', 'D' | 0x80, '(', 'O', 'O', 'D', - ')', '=', 'U', 'H', '5', 'D' | 0x80, 'F', '(', - 'O', 'O', 'T', ')', '=', 'U', 'H', '5', - 'T' | 0x80, '(', 'O', 'O', ')', '=', 'U', 'W', - '5' | 0x80, '(', 'O', '\'', ')', '=', 'O', 'H' | 0x80, - '(', 'O', ')', 'E', '=', 'O', 'W' | 0x80, '(', - 'O', ')', ' ', '=', 'O', 'W' | 0x80, '(', 'O', - 'A', ')', '=', 'O', 'W', '4' | 0x80, ' ', '(', - 'O', 'N', 'L', 'Y', ')', '=', 'O', 'W', - '4', 'N', 'L', 'I', 'Y' | 0x80, ' ', '(', 'O', - 'N', 'C', 'E', ')', '=', 'W', 'A', 'H', - '4', 'N', 'S' | 0x80, '(', 'O', 'N', '\'', 'T', - ')', '=', 'O', 'W', '4', 'N', 'T' | 0x80, 'C', - '(', 'O', ')', 'N', '=', 'A', 'A' | 0x80, '(', - 'O', ')', 'N', 'G', '=', 'A', 'O' | 0x80, ' ', - ':', '^', '(', 'O', ')', 'N', '=', 'A', - 'H' | 0x80, 'I', '(', 'O', 'N', ')', '=', 'U', - 'N' | 0x80, '#', ':', '(', 'O', 'N', ')', '=', - 'U', 'N' | 0x80, '#', '^', '(', 'O', 'N', ')', - '=', 'U', 'N' | 0x80, '(', 'O', ')', 'S', 'T', - '=', 'O', 'W' | 0x80, '(', 'O', 'F', ')', '^', - '=', 'A', 'O', '4', 'F' | 0x80, '(', 'O', 'T', - 'H', 'E', 'R', ')', '=', 'A', 'H', '5', - 'D', 'H', 'E', 'R' | 0x80, 'R', '(', 'O', ')', - 'B', '=', 'R', 'A', 'A' | 0x80, '^', 'R', '(', - 'O', ')', ':', '#', '=', 'O', 'W', '5' | 0x80, - '(', 'O', 'S', 'S', ')', ' ', '=', 'A', - 'O', '5', 'S' | 0x80, '#', ':', '^', '(', 'O', - 'M', ')', '=', 'A', 'H', 'M' | 0x80, '(', 'O', - ')', '=', 'A', 'A' | 0x80, - - ']', 'P' | 0x80, ' ', '(', 'P', ')', ' ', '=', - 'P', 'I', 'Y', '4' | 0x80, '(', 'P', 'H', ')', - '=', 'F' | 0x80, '(', 'P', 'E', 'O', 'P', 'L', - ')', '=', 'P', 'I', 'Y', '5', 'P', 'U', - 'L' | 0x80, '(', 'P', 'O', 'W', ')', '=', 'P', - 'A', 'W', '4' | 0x80, '(', 'P', 'U', 'T', ')', - ' ', '=', 'P', 'U', 'H', 'T' | 0x80, '(', 'P', - ')', 'P', '=' | 0x80, '(', 'P', ')', 'S', '=' | 0x80, - '(', 'P', ')', 'N', '=' | 0x80, '(', 'P', 'R', - 'O', 'F', '.', ')', '=', 'P', 'R', 'O', - 'H', 'F', 'E', 'H', '4', 'S', 'E', 'R' | 0x80, - '(', 'P', ')', '=', 'P' | 0x80, - - ']', 'Q' | 0x80, ' ', '(', 'Q', ')', ' ', '=', - 'K', 'Y', 'U', 'W', '4' | 0x80, '(', 'Q', 'U', - 'A', 'R', ')', '=', 'K', 'W', 'O', 'H', - '5', 'R' | 0x80, '(', 'Q', 'U', ')', '=', 'K', - 'W' | 0x80, '(', 'Q', ')', '=', 'K' | 0x80, ']', 'R' | 0x80, - ' ', '(', 'R', ')', ' ', '=', 'A', 'A', - '5', 'R' | 0x80, ' ', '(', 'R', 'E', ')', '^', - '#', '=', 'R', 'I', 'Y' | 0x80, '(', 'R', ')', - 'R', '=' | 0x80, '(', 'R', ')', '=', 'R' | 0x80, - - ']', 'S' | 0x80, ' ', '(', 'S', ')', ' ', '=', - 'E', 'H', '4', 'S' | 0x80, '(', 'S', 'H', ')', - '=', 'S', 'H' | 0x80, '#', '(', 'S', 'I', 'O', - 'N', ')', '=', 'Z', 'H', 'U', 'N' | 0x80, '(', - 'S', 'O', 'M', 'E', ')', '=', 'S', 'A', - 'H', 'M' | 0x80, '#', '(', 'S', 'U', 'R', ')', - '#', '=', 'Z', 'H', 'E', 'R' | 0x80, '(', 'S', - 'U', 'R', ')', '#', '=', 'S', 'H', 'E', - 'R' | 0x80, '#', '(', 'S', 'U', ')', '#', '=', - 'Z', 'H', 'U', 'W' | 0x80, '#', '(', 'S', 'S', - 'U', ')', '#', '=', 'S', 'H', 'U', 'W' | 0x80, - '#', '(', 'S', 'E', 'D', ')', '=', 'Z', - 'D' | 0x80, '#', '(', 'S', ')', '#', '=', 'Z' | 0x80, - '(', 'S', 'A', 'I', 'D', ')', '=', 'S', - 'E', 'H', 'D' | 0x80, '^', '(', 'S', 'I', 'O', - 'N', ')', '=', 'S', 'H', 'U', 'N' | 0x80, '(', - 'S', ')', 'S', '=' | 0x80, '.', '(', 'S', ')', - ' ', '=', 'Z' | 0x80, '#', ':', '.', 'E', '(', - 'S', ')', ' ', '=', 'Z' | 0x80, '#', ':', '^', - '#', '(', 'S', ')', ' ', '=', 'S' | 0x80, 'U', - '(', 'S', ')', ' ', '=', 'S' | 0x80, ' ', ':', - '#', '(', 'S', ')', ' ', '=', 'Z' | 0x80, '#', - '#', '(', 'S', ')', ' ', '=', 'Z' | 0x80, ' ', - '(', 'S', 'C', 'H', ')', '=', 'S', 'K' | 0x80, - '(', 'S', ')', 'C', '+', '=' | 0x80, '#', '(', - 'S', 'M', ')', '=', 'Z', 'U', 'M' | 0x80, '#', - '(', 'S', 'N', ')', '\'', '=', 'Z', 'U', - 'M' | 0x80, '(', 'S', 'T', 'L', 'E', ')', '=', - 'S', 'U', 'L' | 0x80, '(', 'S', ')', '=', 'S' | 0x80, - - ']', 'T' | 0x80, ' ', '(', 'T', ')', ' ', '=', - 'T', 'I', 'Y', '4' | 0x80, ' ', '(', 'T', 'H', - 'E', ')', ' ', '#', '=', 'D', 'H', 'I', - 'Y' | 0x80, ' ', '(', 'T', 'H', 'E', ')', ' ', - '=', 'D', 'H', 'A', 'X' | 0x80, '(', 'T', 'O', - ')', ' ', '=', 'T', 'U', 'X' | 0x80, ' ', '(', - 'T', 'H', 'A', 'T', ')', '=', 'D', 'H', - 'A', 'E', 'T' | 0x80, ' ', '(', 'T', 'H', 'I', - 'S', ')', ' ', '=', 'D', 'H', 'I', 'H', - 'S' | 0x80, ' ', '(', 'T', 'H', 'E', 'Y', ')', - '=', 'D', 'H', 'E', 'Y' | 0x80, ' ', '(', 'T', - 'H', 'E', 'R', 'E', ')', '=', 'D', 'H', - 'E', 'H', 'R' | 0x80, '(', 'T', 'H', 'E', 'R', - ')', '=', 'D', 'H', 'E', 'R' | 0x80, '(', 'T', - 'H', 'E', 'I', 'R', ')', '=', 'D', 'H', - 'E', 'H', 'R' | 0x80, ' ', '(', 'T', 'H', 'A', - 'N', ')', ' ', '=', 'D', 'H', 'A', 'E', - 'N' | 0x80, ' ', '(', 'T', 'H', 'E', 'M', ')', - ' ', '=', 'D', 'H', 'A', 'E', 'N' | 0x80, '(', - 'T', 'H', 'E', 'S', 'E', ')', ' ', '=', - 'D', 'H', 'I', 'Y', 'Z' | 0x80, ' ', '(', 'T', - 'H', 'E', 'N', ')', '=', 'D', 'H', 'E', - 'H', 'N' | 0x80, '(', 'T', 'H', 'R', 'O', 'U', - 'G', 'H', ')', '=', 'T', 'H', 'R', 'U', - 'W', '4' | 0x80, '(', 'T', 'H', 'O', 'S', 'E', - ')', '=', 'D', 'H', 'O', 'H', 'Z' | 0x80, '(', - 'T', 'H', 'O', 'U', 'G', 'H', ')', ' ', - '=', 'D', 'H', 'O', 'W' | 0x80, '(', 'T', 'O', - 'D', 'A', 'Y', ')', '=', 'T', 'U', 'X', - 'D', 'E', 'Y' | 0x80, '(', 'T', 'O', 'M', 'O', - ')', 'R', 'R', 'O', 'W', '=', 'T', 'U', - 'M', 'A', 'A', '5' | 0x80, '(', 'T', 'O', ')', - 'T', 'A', 'L', '=', 'T', 'O', 'W', '5' | 0x80, - ' ', '(', 'T', 'H', 'U', 'S', ')', '=', - 'D', 'H', 'A', 'H', '4', 'S' | 0x80, '(', 'T', - 'H', ')', '=', 'T', 'H' | 0x80, '#', ':', '(', - 'T', 'E', 'D', ')', '=', 'T', 'I', 'X', - 'D' | 0x80, 'S', '(', 'T', 'I', ')', '#', 'N', - '=', 'C', 'H' | 0x80, '(', 'T', 'I', ')', 'O', - '=', 'S', 'H' | 0x80, '(', 'T', 'I', ')', 'A', - '=', 'S', 'H' | 0x80, '(', 'T', 'I', 'E', 'N', - ')', '=', 'S', 'H', 'U', 'N' | 0x80, '(', 'T', - 'U', 'R', ')', '#', '=', 'C', 'H', 'E', - 'R' | 0x80, '(', 'T', 'U', ')', 'A', '=', 'C', - 'H', 'U', 'W' | 0x80, ' ', '(', 'T', 'W', 'O', - ')', '=', 'T', 'U', 'W' | 0x80, '&', '(', 'T', - ')', 'E', 'N', ' ', '=' | 0x80, '(', 'T', ')', - '=', 'T' | 0x80, - - ']', 'U' | 0x80, ' ', '(', 'U', ')', ' ', '=', - 'Y', 'U', 'W', '4' | 0x80, ' ', '(', 'U', 'N', - ')', 'I', '=', 'Y', 'U', 'W', 'N' | 0x80, ' ', - '(', 'U', 'N', ')', '=', 'A', 'H', 'N' | 0x80, - ' ', '(', 'U', 'P', 'O', 'N', ')', '=', - 'A', 'X', 'P', 'A', 'O', 'N' | 0x80, '@', '(', - 'U', 'R', ')', '#', '=', 'U', 'H', '4', - 'R' | 0x80, '(', 'U', 'R', ')', '#', '=', 'Y', - 'U', 'H', '4', 'R' | 0x80, '(', 'U', 'R', ')', - '=', 'E', 'R' | 0x80, '(', 'U', ')', '^', ' ', - '=', 'A', 'H' | 0x80, '(', 'U', ')', '^', '^', - '=', 'A', 'H', '5' | 0x80, '(', 'U', 'Y', ')', - '=', 'A', 'Y', '5' | 0x80, ' ', 'G', '(', 'U', - ')', '#', '=' | 0x80, 'G', '(', 'U', ')', '%', - '=' | 0x80, 'G', '(', 'U', ')', '#', '=', 'W' | 0x80, - '#', 'N', '(', 'U', ')', '=', 'Y', 'U', - 'W' | 0x80, '@', '(', 'U', ')', '=', 'U', 'W' | 0x80, - '(', 'U', ')', '=', 'Y', 'U', 'W' | 0x80, - - ']', 'V' | 0x80, ' ', '(', 'V', ')', ' ', '=', - 'V', 'I', 'Y', '4' | 0x80, '(', 'V', 'I', 'E', - 'W', ')', '=', 'V', 'Y', 'U', 'W', '5' | 0x80, - '(', 'V', ')', '=', 'V' | 0x80, - - ']', 'W' | 0x80, ' ', '(', 'W', ')', ' ', '=', - 'D', 'A', 'H', '4', 'B', 'U', 'L', 'Y', - 'U', 'W' | 0x80, ' ', '(', 'W', 'E', 'R', 'E', - ')', '=', 'W', 'E', 'R' | 0x80, '(', 'W', 'A', - ')', 'S', 'H', '=', 'W', 'A', 'A' | 0x80, '(', - 'W', 'A', ')', 'S', 'T', '=', 'W', 'E', - 'Y' | 0x80, '(', 'W', 'A', ')', 'S', '=', 'W', - 'A', 'H' | 0x80, '(', 'W', 'A', ')', 'T', '=', - 'W', 'A', 'A' | 0x80, '(', 'W', 'H', 'E', 'R', - 'E', ')', '=', 'W', 'H', 'E', 'H', 'R' | 0x80, - '(', 'W', 'H', 'A', 'T', ')', '=', 'W', - 'H', 'A', 'H', 'T' | 0x80, '(', 'W', 'H', 'O', - 'L', ')', '=', '/', 'H', 'O', 'W', 'L' | 0x80, - '(', 'W', 'H', 'O', ')', '=', '/', 'H', - 'U', 'W' | 0x80, '(', 'W', 'H', ')', '=', 'W', - 'H' | 0x80, '(', 'W', 'A', 'R', ')', '#', '=', - 'W', 'E', 'H', 'R' | 0x80, '(', 'W', 'A', 'R', - ')', '=', 'W', 'A', 'O', 'R' | 0x80, '(', 'W', - 'O', 'R', ')', '^', '=', 'W', 'E', 'R' | 0x80, - '(', 'W', 'R', ')', '=', 'R' | 0x80, '(', 'W', - 'O', 'M', ')', 'A', '=', 'W', 'U', 'H', - 'M' | 0x80, '(', 'W', 'O', 'M', ')', 'E', '=', - 'W', 'I', 'H', 'M' | 0x80, '(', 'W', 'E', 'A', - ')', 'R', '=', 'W', 'E', 'H' | 0x80, '(', 'W', - 'A', 'N', 'T', ')', '=', 'W', 'A', 'A', - '5', 'N', 'T' | 0x80, 'A', 'N', 'S', '(', 'W', - 'E', 'R', ')', '=', 'E', 'R' | 0x80, '(', 'W', - ')', '=', 'W' | 0x80, - - ']', 'X' | 0x80, ' ', '(', 'X', ')', ' ', '=', - 'E', 'H', '4', 'K', 'R' | 0x80, ' ', '(', 'X', - ')', '=', 'Z' | 0x80, '(', 'X', ')', '=', 'K', - 'S' | 0x80, - - ']', 'Y' | 0x80, ' ', '(', 'Y', ')', ' ', '=', - 'W', 'A', 'Y', '4' | 0x80, '(', 'Y', 'O', 'U', - 'N', 'G', ')', '=', 'Y', 'A', 'H', 'N', - 'X' | 0x80, ' ', '(', 'Y', 'O', 'U', 'R', ')', - '=', 'Y', 'O', 'H', 'R' | 0x80, ' ', '(', 'Y', - 'O', 'U', ')', '=', 'Y', 'U', 'W' | 0x80, ' ', - '(', 'Y', 'E', 'S', ')', '=', 'Y', 'E', - 'H', 'S' | 0x80, ' ', '(', 'Y', ')', '=', 'Y' | 0x80, - 'F', '(', 'Y', ')', '=', 'A', 'Y' | 0x80, 'P', - 'S', '(', 'Y', 'C', 'H', ')', '=', 'A', - 'Y', 'K' | 0x80, '#', ':', '^', '(', 'Y', ')', - '=', 'I', 'Y' | 0x80, '#', ':', '^', '(', 'Y', - ')', 'I', '=', 'I', 'Y' | 0x80, ' ', ':', '(', - 'Y', ')', ' ', '=', 'A', 'Y' | 0x80, ' ', ':', - '(', 'Y', ')', '#', '=', 'A', 'Y' | 0x80, ' ', - ':', '(', 'Y', ')', '^', '+', ':', '#', - '=', 'I', 'H' | 0x80, ' ', ':', '(', 'Y', ')', - '^', '#', '=', 'A', 'Y' | 0x80, '(', 'Y', ')', - '=', 'I', 'H' | 0x80, - - ']', 'Z' | 0x80, ' ', '(', 'Z', ')', ' ', '=', - 'Z', 'I', 'Y', '4' | 0x80, '(', 'Z', ')', '=', - 'Z' | 0x80, 'j' | 0x80}; - -const unsigned char rules2[] = { - '(', 'A', ')', '=' | 0x80, '(', '!', ')', '=', - '.' | 0x80, '(', '"', ')', ' ', '=', '-', 'A', - 'H', '5', 'N', 'K', 'W', 'O', 'W', 'T', - '-' | 0x80, '(', '"', ')', '=', 'K', 'W', 'O', - 'W', '4', 'T', '-' | 0x80, '(', '#', ')', '=', - ' ', 'N', 'A', 'H', '4', 'M', 'B', 'E', - 'R' | 0x80, '(', '$', ')', '=', ' ', 'D', 'A', - 'A', '4', 'L', 'E', 'R' | 0x80, '(', '%', ')', - '=', ' ', 'P', 'E', 'R', 'S', 'E', 'H', - '4', 'N', 'T' | 0x80, '(', '&', ')', '=', ' ', - 'A', 'E', 'N', 'D' | 0x80, '(', '\'', ')', '=' | 0x80, - '(', '*', ')', '=', ' ', 'A', 'E', '4', - 'S', 'T', 'E', 'R', 'I', 'H', 'S', 'K' | 0x80, - '(', '+', ')', '=', ' ', 'P', 'L', 'A', - 'H', '4', 'S' | 0x80, '(', ',', ')', '=', ',' | 0x80, - ' ', '(', '-', ')', ' ', '=', '-' | 0x80, '(', - '-', ')', '=' | 0x80, '(', '.', ')', '=', ' ', - 'P', 'O', 'Y', 'N', 'T' | 0x80, '(', '/', ')', - '=', ' ', 'S', 'L', 'A', 'E', '4', 'S', - 'H' | 0x80, '(', '0', ')', '=', ' ', 'Z', 'I', - 'Y', '4', 'R', 'O', 'W' | 0x80, ' ', '(', '1', - 'S', 'T', ')', '=', 'F', 'E', 'R', '4', - 'S', 'T' | 0x80, ' ', '(', '1', '0', 'T', 'H', - ')', '=', 'T', 'E', 'H', '4', 'N', 'T', - 'H' | 0x80, '(', '1', ')', '=', ' ', 'W', 'A', - 'H', '4', 'N' | 0x80, ' ', '(', '2', 'N', 'D', - ')', '=', 'S', 'E', 'H', '4', 'K', 'U', - 'N', 'D' | 0x80, '(', '2', ')', '=', ' ', 'T', - 'U', 'W', '4' | 0x80, ' ', '(', '3', 'R', 'D', - ')', '=', 'T', 'H', 'E', 'R', '4', 'D' | 0x80, - '(', '3', ')', '=', ' ', 'T', 'H', 'R', - 'I', 'Y', '4' | 0x80, '(', '4', ')', '=', ' ', - 'F', 'O', 'H', '4', 'R' | 0x80, ' ', '(', '5', - 'T', 'H', ')', '=', 'F', 'I', 'H', '4', - 'F', 'T', 'H' | 0x80, '(', '5', ')', '=', ' ', - 'F', 'A', 'Y', '4', 'V' | 0x80, ' ', '(', '6', - '4', ')', ' ', '=', 'S', 'I', 'H', '4', - 'K', 'S', 'T', 'I', 'Y', ' ', 'F', 'O', - 'H', 'R' | 0x80, '(', '6', ')', '=', ' ', 'S', - 'I', 'H', '4', 'K', 'S' | 0x80, '(', '7', ')', - '=', ' ', 'S', 'E', 'H', '4', 'V', 'U', - 'N' | 0x80, ' ', '(', '8', 'T', 'H', ')', '=', - 'E', 'Y', '4', 'T', 'H' | 0x80, '(', '8', ')', - '=', ' ', 'E', 'Y', '4', 'T' | 0x80, '(', '9', - ')', '=', ' ', 'N', 'A', 'Y', '4', 'N' | 0x80, - '(', ':', ')', '=', '.' | 0x80, '(', ';', ')', - '=', '.' | 0x80, '(', '<', ')', '=', ' ', 'L', - 'E', 'H', '4', 'S', ' ', 'D', 'H', 'A', - 'E', 'N' | 0x80, '(', '=', ')', '=', ' ', 'I', - 'Y', '4', 'K', 'W', 'U', 'L', 'Z' | 0x80, '(', - '>', ')', '=', ' ', 'G', 'R', 'E', 'Y', - '4', 'T', 'E', 'R', ' ', 'D', 'H', 'A', - 'E', 'N' | 0x80, '(', '?', ')', '=', '?' | 0x80, '(', - '@', ')', '=', ' ', 'A', 'E', '6', 'T' | 0x80, - '(', '^', ')', '=', ' ', 'K', 'A', 'E', - '4', 'R', 'I', 'X', 'T' | 0x80, ']', 'A' | 0x80}; - -//26 items. From 'A' to 'Z' -// positions for mem62 and mem63 for each character -const unsigned char tab37489[] = {0, 149, 247, 162, 57, 197, 6, 126, 199, 38, 55, 78, 145, - 241, 85, 161, 254, 36, 69, 45, 167, 54, 83, 46, 71, 218}; - -const unsigned char tab37515[] = {125, 126, 126, 127, 128, 129, 130, 130, 130, 132, 132, 132, 132, - 132, 133, 135, 135, 136, 136, 137, 138, 139, 139, 140, 140, 140}; - -void STM32SAM::Output8BitAry(int index, unsigned char ary[5]) { - int k; - - uint32_t bufferposOld = bufferpos; - - bufferpos += timetable[oldtimetableindex][index]; - oldtimetableindex = index; - - int sample_uS = bufferpos - bufferposOld; - - uint32_t f = 0; - - // write a little bit in advance - for(k = 0; k < 5; k++) { - // buffer[bufferpos / 50 + k] = ary[k]; - - // f = micros() + sample_uS / (_STM32SAM_SPEED + 1); - // while(micros() < f) { - // }; - f = sample_uS / (_STM32SAM_SPEED + 1); - furi_delay_us(f); - SetAUDIO(ary[k]); - // delayMicroseconds(sample_uS / 5 ); - } - - // SetAUDIO(ary[0]); -} - -void STM32SAM::Output8Bit(int index, unsigned char A) { - unsigned char ary[5] = {A, A, A, A, A}; - Output8BitAry(index, ary); -} - -//written by me because of different table positions. -// mem[47] = ... -// 168=pitches -// 169=frequency1 -// 170=frequency2 -// 171=frequency3 -// 172=amplitude1 -// 173=amplitude2 -// 174=amplitude3 -unsigned char STM32SAM::Read(unsigned char p, unsigned char Y) { - switch(p) { - case 168: - return pitches[Y]; - case 169: - return frequency1[Y]; - case 170: - return frequency2[Y]; - case 171: - return frequency3[Y]; - case 172: - return amplitude1[Y]; - case 173: - return amplitude2[Y]; - case 174: - return amplitude3[Y]; - } - // Serial1.println("Error reading to tables"); - return 0; -} - -void STM32SAM::Write(unsigned char p, unsigned char Y, unsigned char value) { - switch(p) { - case 168: - pitches[Y] = value; - return; - case 169: - frequency1[Y] = value; - return; - case 170: - frequency2[Y] = value; - return; - case 171: - frequency3[Y] = value; - return; - case 172: - amplitude1[Y] = value; - return; - case 173: - amplitude2[Y] = value; - return; - case 174: - amplitude3[Y] = value; - return; - } - //Serial1.println("Error writing to tables\n"); -} - -// ------------------------------------------------------------------------- -//Code48227 -// Render a sampled sound from the sampleTable. -// -// Phoneme Sample Start Sample End -// 32: S* 15 255 -// 33: SH 257 511 -// 34: F* 559 767 -// 35: TH 583 767 -// 36: /H 903 1023 -// 37: /X 1135 1279 -// 38: Z* 84 119 -// 39: ZH 340 375 -// 40: V* 596 639 -// 41: DH 596 631 -// -// 42: CH -// 43: ** 399 511 -// -// 44: J* -// 45: ** 257 276 -// 46: ** -// -// 66: P* -// 67: ** 743 767 -// 68: ** -// -// 69: T* -// 70: ** 231 255 -// 71: ** -// -// The SampledPhonemesTable[] holds flags indicating if a phoneme is -// voiced or not. If the upper 5 bits are zero, the sample is voiced. -// -// Samples in the sampleTable are compressed, with bits being converted to -// bytes from high bit to low, as follows: -// -// unvoiced 0 bit -> X -// unvoiced 1 bit -> 5 -// -// voiced 0 bit -> 6 -// voiced 1 bit -> 24 -// -// Where X is a value from the table: -// -// { 0x18, 0x1A, 0x17, 0x17, 0x17 }; -// -// The index into this table is determined by masking off the lower -// 3 bits from the SampledPhonemesTable: -// -// index = (SampledPhonemesTable[i] & 7) - 1; -// -// For voices samples, samples are interleaved between voiced output. - -// Code48227() -void STM32SAM::RenderSample(unsigned char* mem66) { - int tempA; - // current phoneme's index - mem49 = Y; - - // mask low three bits and subtract 1 get value to - // convert 0 bits on unvoiced samples. - A = mem39 & 7; - X = A - 1; - - // store the result - mem56 = X; - - // determine which offset to use from table { 0x18, 0x1A, 0x17, 0x17, 0x17 } - // T, S, Z 0 0x18 - // CH, J, SH, ZH 1 0x1A - // P, F*, V, TH, DH 2 0x17 - // /H 3 0x17 - // /X 4 0x17 - - // get value from the table - mem53 = tab48426[X]; - mem47 = X; //46016+mem[56]*256 - - // voiced sample? - A = mem39 & 248; - if(A == 0) { - // voiced phoneme: Z*, ZH, V*, DH - Y = mem49; - A = pitches[mem49] >> 4; - - // jump to voiced portion - goto pos48315; - } - - Y = A ^ 255; -pos48274: - - // step through the 8 bits in the sample - mem56 = 8; - - // get the next sample from the table - // mem47*256 = offset to start of samples - A = sampleTable[mem47 * 256 + Y]; -pos48280: - - // left shift to get the high bit - tempA = A; - A = A << 1; - //48281: BCC 48290 - - // bit not set? - if((tempA & 128) == 0) { - // convert the bit to value from table - X = mem53; - //mem[54296] = X; - // output the byte - Output8Bit(1, (X & 0x0f) * 16); - // if X != 0, exit loop - if(X != 0) goto pos48296; - } - - // output a 5 for the on bit - Output8Bit(2, 5 * 16); - - //48295: NOP -pos48296: - - X = 0; - - // decrement counter - mem56--; - - // if not done, jump to top of loop - if(mem56 != 0) goto pos48280; - - // increment position - Y++; - if(Y != 0) goto pos48274; - - // restore values and return - mem44 = 1; - Y = mem49; - return; - - unsigned char phase1; - -pos48315: - // handle voiced samples here - - // number of samples? - phase1 = A ^ 255; - - Y = *mem66; - do { - //pos48321: - - // shift through all 8 bits - mem56 = 8; - //A = Read(mem47, Y); - - // fetch value from table - A = sampleTable[mem47 * 256 + Y]; - - // loop 8 times - //pos48327: - do { - //48327: ASL A - //48328: BCC 48337 - - // left shift and check high bit - tempA = A; - A = A << 1; - if((tempA & 128) != 0) { - // if bit set, output 26 - X = 26; - Output8Bit(3, (X & 0xf) * 16); - } else { - //timetable 4 - // bit is not set, output a 6 - X = 6; - Output8Bit(4, (X & 0xf) * 16); - } - - mem56--; - } while(mem56 != 0); - - // move ahead in the table - Y++; - - // continue until counter done - phase1++; - - } while(phase1 != 0); - // if (phase1 != 0) goto pos48321; - - // restore values and return - A = 1; - mem44 = 1; - *mem66 = Y; - Y = mem49; - return; -} - -// RENDER THE PHONEMES IN THE LIST -// -// The phoneme list is converted into sound through the steps: -// -// 1. Copy each phoneme number of times into the frames list, -// where each frame represents 10 milliseconds of sound. -// -// 2. Determine the transitions lengths between phonemes, and linearly -// interpolate the values across the frames. -// -// 3. Offset the pitches by the fundamental frequency. -// -// 4. Render the each frame. - -//void Code47574() -void STM32SAM::Render() { - unsigned char phase1 = 0; //mem43 - unsigned char phase2 = 0; - unsigned char phase3 = 0; - unsigned char mem66 = 0; - unsigned char mem38 = 0; - unsigned char mem40 = 0; - unsigned char speedcounter = 0; //mem45 - unsigned char mem48 = 0; - int i; - if(phonemeIndexOutput[0] == 255) return; //exit if no data - - A = 0; - X = 0; - mem44 = 0; - - // CREATE FRAMES - // - // The length parameter in the list corresponds to the number of frames - // to expand the phoneme to. Each frame represents 10 milliseconds of time. - // So a phoneme with a length of 7 = 7 frames = 70 milliseconds duration. - // - // The parameters are copied from the phoneme to the frame verbatim. - - // pos47587: - do { - // get the index - Y = mem44; - // get the phoneme at the index - A = phonemeIndexOutput[mem44]; - mem56 = A; - - // if terminal phoneme, exit the loop - if(A == 255) break; - - // period phoneme *. - if(A == 1) { - // add rising inflection - A = 1; - mem48 = 1; - //goto pos48376; - AddInflection(mem48, phase1); - } - /* - if (A == 2) goto pos48372; - */ - - // question mark phoneme? - if(A == 2) { - // create falling inflection - mem48 = 255; - AddInflection(mem48, phase1); - } - // pos47615: - - // get the stress amount (more stress = higher pitch) - phase1 = tab47492[stressOutput[Y] + 1]; - - // get number of frames to write - phase2 = phonemeLengthOutput[Y]; - Y = mem56; - - // copy from the source to the frames list - do { - frequency1[X] = freq1data[Y]; // F1 frequency - frequency2[X] = freq2data[Y]; // F2 frequency - frequency3[X] = freq3data[Y]; // F3 frequency - amplitude1[X] = ampl1data[Y]; // F1 amplitude - amplitude2[X] = ampl2data[Y]; // F2 amplitude - amplitude3[X] = ampl3data[Y]; // F3 amplitude - sampledConsonantFlag[X] = - sampledConsonantFlags[Y]; // phoneme data for sampled consonants - pitches[X] = pitch + phase1; // pitch - X++; - phase2--; - } while(phase2 != 0); - mem44++; - } while(mem44 != 0); - // ------------------- - //pos47694: - - // CREATE TRANSITIONS - // - // Linear transitions are now created to smoothly connect the - // end of one sustained portion of a phoneme to the following - // phoneme. - // - // To do this, three tables are used: - // - // Table Purpose - // ========= ================================================== - // blendRank Determines which phoneme's blend values are used. - // - // blendOut The number of frames at the end of the phoneme that - // will be used to transition to the following phoneme. - // - // blendIn The number of frames of the following phoneme that - // will be used to transition into that phoneme. - // - // In creating a transition between two phonemes, the phoneme - // with the HIGHEST rank is used. Phonemes are ranked on how much - // their identity is based on their transitions. For example, - // vowels are and diphthongs are identified by their sustained portion, - // rather than the transitions, so they are given low values. In contrast, - // stop consonants (P, B, T, K) and glides (Y, L) are almost entirely - // defined by their transitions, and are given high rank values. - // - // Here are the rankings used by SAM: - // - // Rank Type Phonemes - // 2 All vowels IY, IH, etc. - // 5 Diphthong endings YX, WX, ER - // 8 Terminal liquid consonants LX, WX, YX, N, NX - // 9 Liquid consonants L, RX, W - // 10 Glide R, OH - // 11 Glide WH - // 18 Voiceless fricatives S, SH, F, TH - // 20 Voiced fricatives Z, ZH, V, DH - // 23 Plosives, stop consonants P, T, K, KX, DX, CH - // 26 Stop consonants J, GX, B, D, G - // 27-29 Stop consonants (internal) ** - // 30 Unvoiced consonants /H, /X and Q* - // 160 Nasal M - // - // To determine how many frames to use, the two phonemes are - // compared using the blendRank[] table. The phoneme with the - // higher rank is selected. In case of a tie, a blend of each is used: - // - // if blendRank[phoneme1] == blendRank[phomneme2] - // // use lengths from each phoneme - // outBlendFrames = outBlend[phoneme1] - // inBlendFrames = outBlend[phoneme2] - // else if blendRank[phoneme1] > blendRank[phoneme2] - // // use lengths from first phoneme - // outBlendFrames = outBlendLength[phoneme1] - // inBlendFrames = inBlendLength[phoneme1] - // else - // // use lengths from the second phoneme - // // note that in and out are SWAPPED! - // outBlendFrames = inBlendLength[phoneme2] - // inBlendFrames = outBlendLength[phoneme2] - // - // Blend lengths can't be less than zero. - // - // Transitions are assumed to be symetrical, so if the transition - // values for the second phoneme are used, the inBlendLength and - // outBlendLength values are SWAPPED. - // - // For most of the parameters, SAM interpolates over the range of the last - // outBlendFrames-1 and the first inBlendFrames. - // - // The exception to this is the Pitch[] parameter, which is interpolates the - // pitch from the CENTER of the current phoneme to the CENTER of the next - // phoneme. - // - // Here are two examples. First, For example, consider the word "SUN" (S AH N) - // - // Phoneme Duration BlendWeight OutBlendFrames InBlendFrames - // S 2 18 1 3 - // AH 8 2 4 4 - // N 7 8 1 2 - // - // The formant transitions for the output frames are calculated as follows: - // - // flags ampl1 freq1 ampl2 freq2 ampl3 freq3 pitch - // ------------------------------------------------ - // S - // 241 0 6 0 73 0 99 61 Use S (weight 18) for transition instead of AH (weight 2) - // 241 0 6 0 73 0 99 61 <-- (OutBlendFrames-1) = (1-1) = 0 frames - // AH - // 0 2 10 2 66 0 96 59 * <-- InBlendFrames = 3 frames - // 0 4 14 3 59 0 93 57 * - // 0 8 18 5 52 0 90 55 * - // 0 15 22 9 44 1 87 53 - // 0 15 22 9 44 1 87 53 - // 0 15 22 9 44 1 87 53 Use N (weight 8) for transition instead of AH (weight 2). - // 0 15 22 9 44 1 87 53 Since N is second phoneme, reverse the IN and OUT values. - // 0 11 17 8 47 1 98 56 * <-- (InBlendFrames-1) = (2-1) = 1 frames - // N - // 0 8 12 6 50 1 109 58 * <-- OutBlendFrames = 1 - // 0 5 6 5 54 0 121 61 - // 0 5 6 5 54 0 121 61 - // 0 5 6 5 54 0 121 61 - // 0 5 6 5 54 0 121 61 - // 0 5 6 5 54 0 121 61 - // 0 5 6 5 54 0 121 61 - // - // Now, consider the reverse "NUS" (N AH S): - // - // flags ampl1 freq1 ampl2 freq2 ampl3 freq3 pitch - // ------------------------------------------------ - // N - // 0 5 6 5 54 0 121 61 - // 0 5 6 5 54 0 121 61 - // 0 5 6 5 54 0 121 61 - // 0 5 6 5 54 0 121 61 - // 0 5 6 5 54 0 121 61 - // 0 5 6 5 54 0 121 61 Use N (weight 8) for transition instead of AH (weight 2) - // 0 5 6 5 54 0 121 61 <-- (OutBlendFrames-1) = (1-1) = 0 frames - // AH - // 0 8 11 6 51 0 110 59 * <-- InBlendFrames = 2 - // 0 11 16 8 48 0 99 56 * - // 0 15 22 9 44 1 87 53 Use S (weight 18) for transition instead of AH (weight 2) - // 0 15 22 9 44 1 87 53 Since S is second phoneme, reverse the IN and OUT values. - // 0 9 18 5 51 1 90 55 * <-- (InBlendFrames-1) = (3-1) = 2 - // 0 4 14 3 58 1 93 57 * - // S - // 241 2 10 2 65 1 96 59 * <-- OutBlendFrames = 1 - // 241 0 6 0 73 0 99 61 - - A = 0; - mem44 = 0; - mem49 = 0; // mem49 starts at as 0 - X = 0; - while(1) //while No. 1 - { - // get the current and following phoneme - Y = phonemeIndexOutput[X]; - A = phonemeIndexOutput[X + 1]; - X++; - - // exit loop at end token - if(A == 255) break; //goto pos47970; - - // get the ranking of each phoneme - X = A; - mem56 = blendRank[A]; - A = blendRank[Y]; - - // compare the rank - lower rank value is stronger - if(A == mem56) { - // same rank, so use out blend lengths from each phoneme - phase1 = outBlendLength[Y]; - phase2 = outBlendLength[X]; - } else if(A < mem56) { - // first phoneme is stronger, so us it's blend lengths - phase1 = inBlendLength[X]; - phase2 = outBlendLength[X]; - } else { - // second phoneme is stronger, so use it's blend lengths - // note the out/in are swapped - phase1 = outBlendLength[Y]; - phase2 = inBlendLength[Y]; - } - - Y = mem44; - A = mem49 + phonemeLengthOutput[mem44]; // A is mem49 + length - mem49 = A; // mem49 now holds length + position - A = A + phase2; //Maybe Problem because of carry flag - - //47776: ADC 42 - speedcounter = A; - mem47 = 168; - phase3 = mem49 - phase1; // what is mem49 - A = phase1 + phase2; // total transition? - mem38 = A; - - X = A; - X -= 2; - if((X & 128) == 0) - do //while No. 2 - { - //pos47810: - - // mem47 is used to index the tables: - // 168 pitches[] - // 169 frequency1 - // 170 frequency2 - // 171 frequency3 - // 172 amplitude1 - // 173 amplitude2 - // 174 amplitude3 - - mem40 = mem38; - - if(mem47 == 168) // pitch - { - // unlike the other values, the pitches[] interpolates from - // the middle of the current phoneme to the middle of the - // next phoneme - - unsigned char mem36, mem37; - // half the width of the current phoneme - mem36 = phonemeLengthOutput[mem44] >> 1; - // half the width of the next phoneme - mem37 = phonemeLengthOutput[mem44 + 1] >> 1; - // sum the values - mem40 = mem36 + mem37; // length of both halves - mem37 += mem49; // center of next phoneme - mem36 = mem49 - mem36; // center index of current phoneme - A = Read( - mem47, mem37); // value at center of next phoneme - end interpolation value - //A = mem[address]; - - Y = mem36; // start index of interpolation - mem53 = A - Read(mem47, mem36); // value to center of current phoneme - } else { - // value to interpolate to - A = Read(mem47, speedcounter); - // position to start interpolation from - Y = phase3; - // value to interpolate from - mem53 = A - Read(mem47, phase3); - } - - //Code47503(mem40); - // ML : Code47503 is division with remainder, and mem50 gets the sign - - // calculate change per frame - signed char m53 = (signed char)mem53; - mem50 = mem53 & 128; - unsigned char m53abs = abs(m53); - mem51 = m53abs % mem40; //abs((char)m53) % mem40; - mem53 = (unsigned char)((signed char)(m53) / mem40); - - // interpolation range - X = mem40; // number of frames to interpolate over - Y = phase3; // starting frame - - // linearly interpolate values - - mem56 = 0; - //47907: CLC - //pos47908: - while(1) //while No. 3 - { - A = Read(mem47, Y) + mem53; //carry alway cleared - - mem48 = A; - Y++; - X--; - if(X == 0) break; - - mem56 += mem51; - if(mem56 >= mem40) //??? - { - mem56 -= mem40; //carry? is set - //if ((mem56 & 128)==0) - if((mem50 & 128) == 0) { - //47935: BIT 50 - //47937: BMI 47943 - if(mem48 != 0) mem48++; - } else - mem48--; - } - //pos47945: - Write(mem47, Y, mem48); - } //while No. 3 - - //pos47952: - mem47++; - //if (mem47 != 175) goto pos47810; - } while(mem47 != 175); //while No. 2 - //pos47963: - mem44++; - X = mem44; - } //while No. 1 - - //goto pos47701; - //pos47970: - - // add the length of this phoneme - mem48 = mem49 + phonemeLengthOutput[mem44]; - - // ASSIGN PITCH CONTOUR - // - // This subtracts the F1 frequency from the pitch to create a - // pitch contour. Without this, the output would be at a single - // pitch level (monotone). - - // don't adjust pitch if in sing mode - if(!singmode) { - // iterate through the buffer - for(i = 0; i < 256; i++) { - // subtract half the frequency of the formant 1. - // this adds variety to the voice - pitches[i] -= (frequency1[i] >> 1); - } - } - - phase1 = 0; - phase2 = 0; - phase3 = 0; - mem49 = 0; - speedcounter = 72; //sam standard speed - - // RESCALE AMPLITUDE - // - // Rescale volume from a linear scale to decibels. - // - - //amplitude rescaling - for(i = 255; i >= 0; i--) { - amplitude1[i] = amplitudeRescale[amplitude1[i]]; - amplitude2[i] = amplitudeRescale[amplitude2[i]]; - amplitude3[i] = amplitudeRescale[amplitude3[i]]; - } - - Y = 0; - A = pitches[0]; - mem44 = A; - X = A; - mem38 = A - (A >> 2); // 3/4*A ??? - - // PROCESS THE FRAMES - // - // In traditional vocal synthesis, the glottal pulse drives filters, which - // are attenuated to the frequencies of the formants. - // - // SAM generates these formants directly with sin and rectangular waves. - // To simulate them being driven by the glottal pulse, the waveforms are - // reset at the beginning of each glottal pulse. - - //finally the loop for sound output - //pos48078: - while(1) { - // get the sampled information on the phoneme - A = sampledConsonantFlag[Y]; - mem39 = A; - - // unvoiced sampled phoneme? - A = A & 248; - if(A != 0) { - // render the sample for the phoneme - RenderSample(&mem66); - - // skip ahead two in the phoneme buffer - Y += 2; - mem48 -= 2; - } else { - // simulate the glottal pulse and formants - unsigned char ary[5]; - unsigned int p1 = - phase1 * 256; // Fixed point integers because we need to divide later on - unsigned int p2 = phase2 * 256; - unsigned int p3 = phase3 * 256; - int k; - for(k = 0; k < 5; k++) { - signed char sp1 = (signed char)sinus[0xff & (p1 >> 8)]; - signed char sp2 = (signed char)sinus[0xff & (p2 >> 8)]; - signed char rp3 = (signed char)rectangle[0xff & (p3 >> 8)]; - signed int sin1 = sp1 * ((unsigned char)amplitude1[Y] & 0x0f); - signed int sin2 = sp2 * ((unsigned char)amplitude2[Y] & 0x0f); - signed int rect = rp3 * ((unsigned char)amplitude3[Y] & 0x0f); - signed int mux = sin1 + sin2 + rect; - mux /= 32; - mux += 128; // Go from signed to unsigned amplitude - ary[k] = mux; - p1 += frequency1[Y] * 256 / 4; // Compromise, this becomes a shift and works well - p2 += frequency2[Y] * 256 / 4; - p3 += frequency3[Y] * 256 / 4; - } - // output the accumulated value - Output8BitAry(0, ary); - speedcounter--; - if(speedcounter != 0) goto pos48155; - Y++; //go to next amplitude - - // decrement the frame count - mem48--; - } - - // if the frame count is zero, exit the loop - if(mem48 == 0) return; - speedcounter = speed; - pos48155: - - // decrement the remaining length of the glottal pulse - mem44--; - - // finished with a glottal pulse? - if(mem44 == 0) { - pos48159: - // fetch the next glottal pulse length - A = pitches[Y]; - mem44 = A; - A = A - (A >> 2); - mem38 = A; - - // reset the formant wave generators to keep them in - // sync with the glottal pulse - phase1 = 0; - phase2 = 0; - phase3 = 0; - continue; - } - - // decrement the count - mem38--; - - // is the count non-zero and the sampled flag is zero? - if((mem38 != 0) || (mem39 == 0)) { - // reset the phase of the formants to match the pulse - phase1 += frequency1[Y]; - phase2 += frequency2[Y]; - phase3 += frequency3[Y]; - continue; - } - - // voiced sampled phonemes interleave the sample with the - // glottal pulse. The sample flag is non-zero, so render - // the sample for the phoneme. - RenderSample(&mem66); - goto pos48159; - } //while - - // The following code is never reached. It's left over from when - // the voiced sample code was part of this loop, instead of part - // of RenderSample(); - - //pos48315: - int tempA; - phase1 = A ^ 255; - Y = mem66; - do { - //pos48321: - - mem56 = 8; - A = Read(mem47, Y); - - //pos48327: - do { - //48327: ASL A - //48328: BCC 48337 - tempA = A; - A = A << 1; - if((tempA & 128) != 0) { - X = 26; - // mem[54296] = X; - bufferpos += 150; - // - // - // buffer[bufferpos / 50] = (X & 15) * 16; - // - // - - } else { - //mem[54296] = 6; - X = 6; - bufferpos += 150; - // - // buffer[bufferpos / 50] = (X & 15) * 16; - // - // - } - - for(X = wait2; X > 0; X--) - ; //wait - mem56--; - } while(mem56 != 0); - - Y++; - phase1++; - - } while(phase1 != 0); - // if (phase1 != 0) goto pos48321; - A = 1; - mem44 = 1; - mem66 = Y; - Y = mem49; - return; -} - -// Create a rising or falling inflection 30 frames prior to -// index X. A rising inflection is used for questions, and -// a falling inflection is used for statements. - -void STM32SAM::AddInflection(unsigned char mem48, unsigned char phase1) { - //pos48372: - // mem48 = 255; - //pos48376: - - // store the location of the punctuation - mem49 = X; - A = X; - int Atemp = A; - - // backup 30 frames - A = A - 30; - // if index is before buffer, point to start of buffer - if(Atemp <= 30) A = 0; - X = A; - - // FIXME: Explain this fix better, it's not obvious - // ML : A =, fixes a problem with invalid pitch with '.' - while((A = pitches[X]) == 127) X++; - -pos48398: - //48398: CLC - //48399: ADC 48 - - // add the inflection direction - A += mem48; - phase1 = A; - - // set the inflection - pitches[X] = A; -pos48406: - - // increment the position - X++; - - // exit if the punctuation has been reached - if(X == mem49) return; //goto pos47615; - if(pitches[X] == 255) goto pos48406; - A = phase1; - goto pos48398; -} - -/* - SAM's voice can be altered by changing the frequencies of the - mouth formant (F1) and the throat formant (F2). Only the voiced - phonemes (5-29 and 48-53) are altered. -*/ -void STM32SAM::SetMouthThroat() { - unsigned char initialFrequency; - unsigned char newFrequency = 0; - //unsigned char mouth; //mem38880 - //unsigned char throat; //mem38881 - - // mouth formants (F1) 5..29 - unsigned char mouthFormants5_29[30] = {0, 0, 0, 0, 0, 10, 14, 19, 24, 27, - 23, 21, 16, 20, 14, 18, 14, 18, 18, 16, - 13, 15, 11, 18, 14, 11, 9, 6, 6, 6}; - - // throat formants (F2) 5..29 - unsigned char throatFormants5_29[30] = {255, 255, 255, 255, 255, 84, 73, 67, 63, 40, - 44, 31, 37, 45, 73, 49, 36, 30, 51, 37, - 29, 69, 24, 50, 30, 24, 83, 46, 54, 86}; - - // there must be no zeros in this 2 tables - // formant 1 frequencies (mouth) 48..53 - unsigned char mouthFormants48_53[6] = {19, 27, 21, 27, 18, 13}; - - // formant 2 frequencies (throat) 48..53 - unsigned char throatFormants48_53[6] = {72, 39, 31, 43, 30, 34}; - - unsigned char pos = 5; //mem39216 - //pos38942: - // recalculate formant frequencies 5..29 for the mouth (F1) and throat (F2) - while(pos != 30) { - // recalculate mouth frequency - initialFrequency = mouthFormants5_29[pos]; - if(initialFrequency != 0) newFrequency = trans(mouth, initialFrequency); - freq1data[pos] = newFrequency; - - // recalculate throat frequency - initialFrequency = throatFormants5_29[pos]; - if(initialFrequency != 0) newFrequency = trans(throat, initialFrequency); - freq2data[pos] = newFrequency; - pos++; - } - - //pos39059: - // recalculate formant frequencies 48..53 - pos = 48; - Y = 0; - while(pos != 54) { - // recalculate F1 (mouth formant) - initialFrequency = mouthFormants48_53[Y]; - newFrequency = trans(mouth, initialFrequency); - freq1data[pos] = newFrequency; - - // recalculate F2 (throat formant) - initialFrequency = throatFormants48_53[Y]; - newFrequency = trans(throat, initialFrequency); - freq2data[pos] = newFrequency; - Y++; - pos++; - } -} - -//return = (mem39212*mem39213) >> 1 -unsigned char STM32SAM::trans(unsigned char mem39212, unsigned char mem39213) { - //pos39008: - unsigned char carry; - int temp; - unsigned char mem39214, mem39215; - A = 0; - mem39215 = 0; - mem39214 = 0; - X = 8; - do { - carry = mem39212 & 1; - mem39212 = mem39212 >> 1; - if(carry != 0) { - /* - 39018: LSR 39212 - 39021: BCC 39033 - */ - carry = 0; - A = mem39215; - temp = (int)A + (int)mem39213; - A = A + mem39213; - if(temp > 255) carry = 1; - mem39215 = A; - } - temp = mem39215 & 1; - mem39215 = (mem39215 >> 1) | (carry ? 128 : 0); - carry = temp; - //39033: ROR 39215 - X--; - } while(X != 0); - temp = mem39214 & 128; - mem39214 = (mem39214 << 1) | (carry ? 1 : 0); - carry = temp; - temp = mem39215 & 128; - mem39215 = (mem39215 << 1) | (carry ? 1 : 0); - carry = temp; - - return mem39215; -} - -//////////////////////////////////////////////////////////////////////////////////////////// -// -// Sam -// -//////////////////////////////////////////////////////////////////////////////////////////// - -//char input[]={"/HAALAOAO MAYN NAAMAEAE IHSTT SAEBAASTTIHAAN \x9b\x9b\0"}; -//unsigned char input[]={"/HAALAOAO \x9b\0"}; -//unsigned char input[]={"AA \x9b\0"}; -//unsigned char input[] = {"GUH5DEHN TAEG\x9b\0"}; - -//unsigned char input[]={"AY5 AEM EY TAO4LXKIHNX KAX4MPYUX4TAH. GOW4 AH/HEH3D PAHNK.MEYK MAY8 DEY.\x9b\0"}; -//unsigned char input[]={"/HEH3LOW2, /HAW AH YUX2 TUXDEY. AY /HOH3P YUX AH FIYLIHNX OW4 KEY.\x9b\0"}; -//unsigned char input[]={"/HEY2, DHIHS IH3Z GREY2T. /HAH /HAH /HAH.AYL BIY5 BAEK.\x9b\0"}; -//unsigned char input[]={"/HAH /HAH /HAH \x9b\0"}; -//unsigned char input[]={"/HAH /HAH /HAH.\x9b\0"}; -//unsigned char input[]={".TUW BIY5Y3,, OHR NAA3T - TUW BIY5IYIY., DHAE4T IHZ DHAH KWEH4SCHAHN.\x9b\0"}; -//unsigned char input[]={"/HEY2, DHIHS \x9b\0"}; - -//unsigned char input[]={" IYIHEHAEAAAHAOOHUHUXERAXIX \x9b\0"}; -//unsigned char input[]={" RLWWYMNNXBDGJZZHVDH \x9b\0"}; -//unsigned char input[]={" SSHFTHPTKCH/H \x9b\0"}; - -//unsigned char input[]={" EYAYOYAWOWUW ULUMUNQ YXWXRXLX/XDX\x9b\0"}; - -void STM32SAM::SetInput(char* _input) { - int i, l; - l = strlen(_input); - if(l > 254) l = 254; - for(i = 0; i < l; i++) { - input[i] = _input[i]; - } - input[l] = 0; -} - -// 168=pitches -// 169=frequency1 -// 170=frequency2 -// 171=frequency3 -// 172=amplitude1 -// 173=amplitude2 -// 174=amplitude3 - -void STM32SAM::Init() { - bufferpos = 0; - int i; - SetMouthThroat(); - - bufferpos = 0; - // TODO, check for free the memory, 10 seconds of output should be more than enough - //buffer = malloc(22050*10); - - // buffer = (char*) calloc(1, sizeof(char)); - - /* - freq2data = &mem[45136]; - freq1data = &mem[45056]; - freq3data = &mem[45216]; - */ - //pitches = &mem[43008]; - /* - frequency1 = &mem[43264]; - frequency2 = &mem[43520]; - frequency3 = &mem[43776]; - */ - /* - amplitude1 = &mem[44032]; - amplitude2 = &mem[44288]; - amplitude3 = &mem[44544]; - */ - //phoneme = &mem[39904]; - /* - ampl1data = &mem[45296]; - ampl2data = &mem[45376]; - ampl3data = &mem[45456]; - */ - - for(i = 0; i < 256; i++) { - stress[i] = 0; - phonemeLength[i] = 0; - } - - for(i = 0; i < 60; i++) { - phonemeIndexOutput[i] = 0; - stressOutput[i] = 0; - phonemeLengthOutput[i] = 0; - } - phonemeindex[255] = - 255; //to prevent buffer overflow // ML : changed from 32 to 255 to stop freezing with long inputs -} - -//int Code39771() -int STM32SAM::SAMMain() { - Init(); - phonemeindex[255] = 32; //to prevent buffer overflow - - if(!Parser1()) { - return 0; - } - - Parser2(); - CopyStress(); - SetPhonemeLength(); - AdjustLengths(); - Code41240(); - do { - A = phonemeindex[X]; - if(A > 80) { - phonemeindex[X] = 255; - break; // error: delete all behind it - } - X++; - } while(X != 0); - - //pos39848: - InsertBreath(); - - //mem[40158] = 255; - - PrepareOutput(); - - return 1; -} - -//void Code48547() -void STM32SAM::PrepareOutput() { - A = 0; - X = 0; - Y = 0; - - //pos48551: - while(1) { - A = phonemeindex[X]; - if(A == 255) { - A = 255; - phonemeIndexOutput[Y] = 255; - Render(); - return; - } - if(A == 254) { - X++; - int temp = X; - //mem[48546] = X; - phonemeIndexOutput[Y] = 255; - Render(); - //X = mem[48546]; - X = temp; - Y = 0; - continue; - } - - if(A == 0) { - X++; - continue; - } - - phonemeIndexOutput[Y] = A; - phonemeLengthOutput[Y] = phonemeLength[X]; - stressOutput[Y] = stress[X]; - X++; - Y++; - } -} - -//void Code41014() -void STM32SAM::Insert( - unsigned char position /*var57*/, - unsigned char mem60, - unsigned char mem59, - unsigned char mem58) { - int i; - for(i = 253; i >= position; i--) // ML : always keep last safe-guarding 255 - { - phonemeindex[i + 1] = phonemeindex[i]; - phonemeLength[i + 1] = phonemeLength[i]; - stress[i + 1] = stress[i]; - } - - phonemeindex[position] = mem60; - phonemeLength[position] = mem59; - stress[position] = mem58; - return; -} - -//void Code48431() -void STM32SAM::InsertBreath() { - unsigned char mem54; - unsigned char mem55; - unsigned char index; //variable Y - mem54 = 255; - X++; - mem55 = 0; - unsigned char mem66 = 0; - while(1) { - //pos48440: - X = mem66; - index = phonemeindex[X]; - if(index == 255) return; - mem55 += phonemeLength[X]; - - if(mem55 < 232) { - if(index != 254) // ML : Prevents an index out of bounds problem - { - A = flags2[index] & 1; - if(A != 0) { - X++; - mem55 = 0; - Insert(X, 254, mem59, 0); - mem66++; - mem66++; - continue; - } - } - if(index == 0) mem54 = X; - mem66++; - continue; - } - X = mem54; - phonemeindex[X] = 31; // 'Q*' glottal stop - phonemeLength[X] = 4; - stress[X] = 0; - X++; - mem55 = 0; - Insert(X, 254, mem59, 0); - X++; - mem66 = X; - } -} - -// Iterates through the phoneme buffer, copying the stress value from -// the following phoneme under the following circumstance: - -// 1. The current phoneme is voiced, excluding plosives and fricatives -// 2. The following phoneme is voiced, excluding plosives and fricatives, and -// 3. The following phoneme is stressed -// -// In those cases, the stress value+1 from the following phoneme is copied. -// -// For example, the word LOITER is represented as LOY5TER, with as stress -// of 5 on the diphtong OY. This routine will copy the stress value of 6 (5+1) -// to the L that precedes it. - -//void Code41883() -void STM32SAM::CopyStress() { - // loop thought all the phonemes to be output - unsigned char pos = 0; //mem66 - while(1) { - // get the phomene - Y = phonemeindex[pos]; - - // exit at end of buffer - if(Y == 255) return; - - // if CONSONANT_FLAG set, skip - only vowels get stress - if((flags[Y] & 64) == 0) { - pos++; - continue; - } - // get the next phoneme - Y = phonemeindex[pos + 1]; - if(Y == 255) //prevent buffer overflow - { - pos++; - continue; - } else - // if the following phoneme is a vowel, skip - if((flags[Y] & 128) == 0) { - pos++; - continue; - } - - // get the stress value at the next position - Y = stress[pos + 1]; - - // if next phoneme is not stressed, skip - if(Y == 0) { - pos++; - continue; - } - - // if next phoneme is not a VOWEL OR ER, skip - if((Y & 128) != 0) { - pos++; - continue; - } - - // copy stress from prior phoneme to this one - stress[pos] = Y + 1; - - // advance pointer - pos++; - } -} - -// The input[] buffer contains a string of phonemes and stress markers along -// the lines of: -// -// DHAX KAET IHZ AH5GLIY. <0x9B> -// -// The byte 0x9B marks the end of the buffer. Some phonemes are 2 bytes -// long, such as "DH" and "AX". Others are 1 byte long, such as "T" and "Z". -// There are also stress markers, such as "5" and ".". -// -// The first character of the phonemes are stored in the table signInputTable1[]. -// The second character of the phonemes are stored in the table signInputTable2[]. -// The stress characters are arranged in low to high stress order in stressInputTable[]. -// -// The following process is used to parse the input[] buffer: -// -// Repeat until the <0x9B> character is reached: -// -// First, a search is made for a 2 character match for phonemes that do not -// end with the '*' (wildcard) character. On a match, the index of the phoneme -// is added to phonemeIndex[] and the buffer position is advanced 2 bytes. -// -// If this fails, a search is made for a 1 character match against all -// phoneme names ending with a '*' (wildcard). If this succeeds, the -// phoneme is added to phonemeIndex[] and the buffer position is advanced -// 1 byte. -// -// If this fails, search for a 1 character match in the stressInputTable[]. -// If this succeeds, the stress value is placed in the last stress[] table -// at the same index of the last added phoneme, and the buffer position is -// advanced by 1 byte. -// -// If this fails, return a 0. -// -// On success: -// -// 1. phonemeIndex[] will contain the index of all the phonemes. -// 2. The last index in phonemeIndex[] will be 255. -// 3. stress[] will contain the stress value for each phoneme - -// input[] holds the string of phonemes, each two bytes wide -// signInputTable1[] holds the first character of each phoneme -// signInputTable2[] holds te second character of each phoneme -// phonemeIndex[] holds the indexes of the phonemes after parsing input[] -// -// The parser scans through the input[], finding the names of the phonemes -// by searching signInputTable1[] and signInputTable2[]. On a match, it -// copies the index of the phoneme into the phonemeIndexTable[]. -// -// The character <0x9B> marks the end of text in input[]. When it is reached, -// the index 255 is placed at the end of the phonemeIndexTable[], and the -// function returns with a 1 indicating success. -int STM32SAM::Parser1() { - int i; - unsigned char sign1; - unsigned char sign2; - unsigned char position = 0; - X = 0; - A = 0; - Y = 0; - - // CLEAR THE STRESS TABLE - for(i = 0; i < 256; i++) stress[i] = 0; - - // THIS CODE MATCHES THE PHONEME LETTERS TO THE TABLE - // pos41078: - while(1) { - // GET THE FIRST CHARACTER FROM THE PHONEME BUFFER - sign1 = input[X]; - // TEST FOR 155 (�) END OF LINE MARKER - if(sign1 == 155) { - // MARK ENDPOINT AND RETURN - phonemeindex[position] = 255; //mark endpoint - // REACHED END OF PHONEMES, SO EXIT - return 1; //all ok - } - - // GET THE NEXT CHARACTER FROM THE BUFFER - X++; - sign2 = input[X]; - - // NOW sign1 = FIRST CHARACTER OF PHONEME, AND sign2 = SECOND CHARACTER OF PHONEME - - // TRY TO MATCH PHONEMES ON TWO TWO-CHARACTER NAME - // IGNORE PHONEMES IN TABLE ENDING WITH WILDCARDS - - // SET INDEX TO 0 - Y = 0; - pos41095: - - // GET FIRST CHARACTER AT POSITION Y IN signInputTable - // --> should change name to PhonemeNameTable1 - A = signInputTable1[Y]; - - // FIRST CHARACTER MATCHES? - if(A == sign1) { - // GET THE CHARACTER FROM THE PhonemeSecondLetterTable - A = signInputTable2[Y]; - // NOT A SPECIAL AND MATCHES SECOND CHARACTER? - if((A != '*') && (A == sign2)) { - // STORE THE INDEX OF THE PHONEME INTO THE phomeneIndexTable - phonemeindex[position] = Y; - - // ADVANCE THE POINTER TO THE phonemeIndexTable - position++; - // ADVANCE THE POINTER TO THE phonemeInputBuffer - X++; - - // CONTINUE PARSING - continue; - } - } - - // NO MATCH, TRY TO MATCH ON FIRST CHARACTER TO WILDCARD NAMES (ENDING WITH '*') - - // ADVANCE TO THE NEXT POSITION - Y++; - // IF NOT END OF TABLE, CONTINUE - if(Y != 81) goto pos41095; - - // REACHED END OF TABLE WITHOUT AN EXACT (2 CHARACTER) MATCH. - // THIS TIME, SEARCH FOR A 1 CHARACTER MATCH AGAINST THE WILDCARDS - - // RESET THE INDEX TO POINT TO THE START OF THE PHONEME NAME TABLE - Y = 0; - pos41134: - // DOES THE PHONEME IN THE TABLE END WITH '*'? - if(signInputTable2[Y] == '*') { - // DOES THE FIRST CHARACTER MATCH THE FIRST LETTER OF THE PHONEME - if(signInputTable1[Y] == sign1) { - // SAVE THE POSITION AND MOVE AHEAD - phonemeindex[position] = Y; - - // ADVANCE THE POINTER - position++; - - // CONTINUE THROUGH THE LOOP - continue; - } - } - Y++; - if(Y != 81) goto pos41134; //81 is size of PHONEME NAME table - - // FAILED TO MATCH WITH A WILDCARD. ASSUME THIS IS A STRESS - // CHARACTER. SEARCH THROUGH THE STRESS TABLE - - // SET INDEX TO POSITION 8 (END OF STRESS TABLE) - Y = 8; - - // WALK BACK THROUGH TABLE LOOKING FOR A MATCH - while((sign1 != stressInputTable[Y]) && (Y > 0)) { - // DECREMENT INDEX - Y--; - } - - // REACHED THE END OF THE SEARCH WITHOUT BREAKING OUT OF LOOP? - if(Y == 0) { - //mem[39444] = X; - //41181: JSR 42043 //Error - // FAILED TO MATCH ANYTHING, RETURN 0 ON FAILURE - return 0; - } - // SET THE STRESS FOR THE PRIOR PHONEME - stress[position - 1] = Y; - } //while -} - -//change phonemelength depedendent on stress -//void Code41203() -void STM32SAM::SetPhonemeLength() { - unsigned char A; - int position = 0; - while(phonemeindex[position] != 255) { - A = stress[position]; - //41218: BMI 41229 - if((A == 0) || ((A & 128) != 0)) { - phonemeLength[position] = phonemeLengthTable[phonemeindex[position]]; - } else { - phonemeLength[position] = phonemeStressedLengthTable[phonemeindex[position]]; - } - position++; - } -} - -void STM32SAM::Code41240() { - unsigned char pos = 0; - - while(phonemeindex[pos] != 255) { - unsigned char index; //register AC - X = pos; - index = phonemeindex[pos]; - if((flags[index] & 2) == 0) { - pos++; - continue; - } else if((flags[index] & 1) == 0) { - Insert(pos + 1, index + 1, phonemeLengthTable[index + 1], stress[pos]); - Insert(pos + 2, index + 2, phonemeLengthTable[index + 2], stress[pos]); - pos += 3; - continue; - } - - do { - X++; - A = phonemeindex[X]; - } while(A == 0); - - if(A != 255) { - if((flags[A] & 8) != 0) { - pos++; - continue; - } - if((A == 36) || (A == 37)) { - pos++; // '/H' '/X' - continue; - } - } - - Insert(pos + 1, index + 1, phonemeLengthTable[index + 1], stress[pos]); - Insert(pos + 2, index + 2, phonemeLengthTable[index + 2], stress[pos]); - pos += 3; - }; -} - -// Rewrites the phonemes using the following rules: -// -// -> WX -// -> YX -// UL -> AX L -// UM -> AX M -// -> Q -// T R -> CH R -// D R -> J R -// R -> RX -// L -> LX -// G S -> G Z -// K -> KX -// G -> GX -// S P -> S B -// S T -> S D -// S K -> S G -// S KX -> S GX -// UW -> UX -// CH -> CH CH' (CH requires two phonemes to represent it) -// J -> J J' (J requires two phonemes to represent it) -// T -> DX -// D -> DX - -//void Code41397() -void STM32SAM::Parser2() { - unsigned char pos = 0; //mem66; - unsigned char mem58 = 0; - - // Loop through phonemes - while(1) { - // SET X TO THE CURRENT POSITION - X = pos; - // GET THE PHONEME AT THE CURRENT POSITION - A = phonemeindex[pos]; - - // Is phoneme pause? - if(A == 0) { - // Move ahead to the - pos++; - continue; - } - - // If end of phonemes flag reached, exit routine - if(A == 255) return; - - // Copy the current phoneme index to Y - Y = A; - - // RULE: - // -> WX - // -> YX - // Example: OIL, COW - - // Check for DIPHTONG - if((flags[A] & 16) == 0) goto pos41457; - - // Not a diphthong. Get the stress - mem58 = stress[pos]; - - // End in IY sound? - A = flags[Y] & 32; - - // If ends with IY, use YX, else use WX - if(A == 0) - A = 20; - else - A = 21; // 'WX' = 20 'YX' = 21 - //pos41443: - // Insert at WX or YX following, copying the stress - - Insert(pos + 1, A, mem59, mem58); - X = pos; - // Jump to ??? - goto pos41749; - - pos41457: - - // RULE: - // UL -> AX L - // Example: MEDDLE - - // Get phoneme - A = phonemeindex[X]; - // Skip this rule if phoneme is not UL - if(A != 78) goto pos41487; // 'UL' - A = 24; // 'L' //change 'UL' to 'AX L' - - pos41466: - // Get current phoneme stress - mem58 = stress[X]; - - // Change UL to AX - phonemeindex[X] = 13; // 'AX' - // Perform insert. Note code below may jump up here with different values - Insert(X + 1, A, mem59, mem58); - pos++; - // Move to next phoneme - continue; - - pos41487: - - // RULE: - // UM -> AX M - // Example: ASTRONOMY - - // Skip rule if phoneme != UM - if(A != 79) goto pos41495; // 'UM' - // Jump up to branch - replaces current phoneme with AX and continues - A = 27; // 'M' //change 'UM' to 'AX M' - - goto pos41466; - pos41495: - - // RULE: - // UN -> AX N - // Example: FUNCTION - - // Skip rule if phoneme != UN - if(A != 80) goto pos41503; // 'UN' - - // Jump up to branch - replaces current phoneme with AX and continues - A = 28; // 'N' //change UN to 'AX N' - - goto pos41466; - pos41503: - - // RULE: - // -> Q - // EXAMPLE: AWAY EIGHT - - Y = A; - // VOWEL set? - A = flags[A] & 128; - - // Skip if not a vowel - if(A != 0) { - // Get the stress - A = stress[X]; - - // If stressed... - if(A != 0) { - // Get the following phoneme - X++; - A = phonemeindex[X]; - // If following phoneme is a pause - - if(A == 0) { - // Get the phoneme following pause - X++; - Y = phonemeindex[X]; - - // Check for end of buffer flag - if(Y == 255) //buffer overflow - // ??? Not sure about these flags - A = 65 & 128; - else - // And VOWEL flag to current phoneme's flags - A = flags[Y] & 128; - - // If following phonemes is not a pause - if(A != 0) { - // If the following phoneme is not stressed - A = stress[X]; - if(A != 0) { - // 31 = 'Q' - Insert(X, 31, mem59, 0); - pos++; - continue; - } - } - } - } - } - - // RULES FOR PHONEMES BEFORE R - // T R -> CH R - // Example: TRACK - - // Get current position and phoneme - X = pos; - A = phonemeindex[pos]; - if(A != 23) goto pos41611; // 'R' - - // Look at prior phoneme - X--; - A = phonemeindex[pos - 1]; - //pos41567: - if(A == 69) // 'T' - { - phonemeindex[pos - 1] = 42; - goto pos41779; - } - - // RULES FOR PHONEMES BEFORE R - // D R -> J R - // Example: DRY - - // Prior phonemes D? - if(A == 57) // 'D' - { - // Change D to J - phonemeindex[pos - 1] = 44; - - goto pos41788; - } - - // RULES FOR PHONEMES BEFORE R - // R -> RX - // Example: ART - - // If vowel flag is set change R to RX - A = flags[A] & 128; - - if(A != 0) phonemeindex[pos] = 18; // 'RX' - - // continue to next phoneme - pos++; - continue; - - pos41611: - - // RULE: - // L -> LX - // Example: ALL - - // Is phoneme L? - if(A == 24) // 'L' - { - // If prior phoneme does not have VOWEL flag set, move to next phoneme - if((flags[phonemeindex[pos - 1]] & 128) == 0) { - pos++; - continue; - } - // Prior phoneme has VOWEL flag set, so change L to LX and move to next phoneme - - phonemeindex[X] = 19; // 'LX' - pos++; - continue; - } - - // RULE: - // G S -> G Z - // - // Can't get to fire - - // 1. The G -> GX rule intervenes - // 2. Reciter already replaces GS -> GZ - - // Is current phoneme S? - if(A == 32) // 'S' - { - // If prior phoneme is not G, move to next phoneme - if(phonemeindex[pos - 1] != 60) { - pos++; - continue; - } - // Replace S with Z and move on - - phonemeindex[pos] = 38; // 'Z' - pos++; - continue; - } - - // RULE: - // K -> KX - // Example: COW - - // Is current phoneme K? - if(A == 72) // 'K' - { - // Get next phoneme - Y = phonemeindex[pos + 1]; - // If at end, replace current phoneme with KX - if(Y == 255) - phonemeindex[pos] = 75; // ML : prevents an index out of bounds problem - else { - // VOWELS AND DIPHTONGS ENDING WITH IY SOUND flag set? - A = flags[Y] & 32; - - // Replace with KX - if(A == 0) phonemeindex[pos] = 75; // 'KX' - } - } else - - // RULE: - // G -> GX - // Example: GO - - // Is character a G? - if(A == 60) // 'G' - { - // Get the following character - unsigned char index = phonemeindex[pos + 1]; - - // At end of buffer? - if(index == 255) //prevent buffer overflow - { - pos++; - continue; - } else - // If diphtong ending with YX, move continue processing next phoneme - if((flags[index] & 32) != 0) { - pos++; - continue; - } - // replace G with GX and continue processing next phoneme - - phonemeindex[pos] = 63; // 'GX' - pos++; - continue; - } - - // RULE: - // S P -> S B - // S T -> S D - // S K -> S G - // S KX -> S GX - // Examples: SPY, STY, SKY, SCOWL - - Y = phonemeindex[pos]; - //pos41719: - // Replace with softer version? - A = flags[Y] & 1; - if(A == 0) goto pos41749; - A = phonemeindex[pos - 1]; - if(A != 32) // 'S' - { - A = Y; - goto pos41812; - } - // Replace with softer version - - phonemeindex[pos] = Y - 12; - pos++; - continue; - - pos41749: - - // RULE: - // UW -> UX - // - // Example: NEW, DEW, SUE, ZOO, THOO, TOO - - // UW -> UX - - A = phonemeindex[X]; - if(A == 53) // 'UW' - { - // ALVEOLAR flag set? - Y = phonemeindex[X - 1]; - A = flags2[Y] & 4; - // If not set, continue processing next phoneme - if(A == 0) { - pos++; - continue; - } - - phonemeindex[X] = 16; - pos++; - continue; - } - pos41779: - - // RULE: - // CH -> CH CH' (CH requires two phonemes to represent it) - // Example: CHEW - - if(A == 42) // 'CH' - { - // pos41783: - - Insert(X + 1, A + 1, mem59, stress[X]); - pos++; - continue; - } - - pos41788: - - // RULE: - // J -> J J' (J requires two phonemes to represent it) - // Example: JAY - - if(A == 44) // 'J' - { - Insert(X + 1, A + 1, mem59, stress[X]); - pos++; - continue; - } - - // Jump here to continue - pos41812: - - // RULE: Soften T following vowel - // NOTE: This rule fails for cases such as "ODD" - // T -> DX - // D -> DX - // Example: PARTY, TARDY - - // Past this point, only process if phoneme is T or D - - if(A != 69) // 'T' - if(A != 57) { - pos++; // 'D' - continue; - } - //pos41825: - - // If prior phoneme is not a vowel, continue processing phonemes - if((flags[phonemeindex[X - 1]] & 128) == 0) { - pos++; - continue; - } - - // Get next phoneme - X++; - A = phonemeindex[X]; - //pos41841 - // Is the next phoneme a pause? - if(A != 0) { - // If next phoneme is not a pause, continue processing phonemes - if((flags[A] & 128) == 0) { - pos++; - continue; - } - // If next phoneme is stressed, continue processing phonemes - // FIXME: How does a pause get stressed? - if(stress[X] != 0) { - pos++; - continue; - } - //pos41856: - // Set phonemes to DX - - phonemeindex[pos] = 30; // 'DX' - } else { - A = phonemeindex[X + 1]; - if(A == 255) //prevent buffer overflow - A = 65 & 128; - else - // Is next phoneme a vowel or ER? - A = flags[A] & 128; - - if(A != 0) phonemeindex[pos] = 30; // 'DX' - } - - pos++; - - } // while -} // parser 2 - -// Applies various rules that adjust the lengths of phonemes -// -// Lengthen or between and by 1.5 -// - decrease length by 1 -// - decrease vowel by 1/8th -// - increase vowel by 1/2 + 1 -// - set nasal = 5, consonant = 6 -// {optional silence} - shorten both to 1/2 + 1 -// - decrease by 2 - -//void Code48619() -void STM32SAM::AdjustLengths() { - // LENGTHEN VOWELS PRECEDING PUNCTUATION - // - // Search for punctuation. If found, back up to the first vowel, then - // process all phonemes between there and up to (but not including) the punctuation. - // If any phoneme is found that is a either a fricative or voiced, the duration is - // increased by (length * 1.5) + 1 - - // loop index - X = 0; - unsigned char index; - - // iterate through the phoneme list - unsigned char loopIndex = 0; - while(1) { - // get a phoneme - index = phonemeindex[X]; - - // exit loop if end on buffer token - if(index == 255) break; - - // not punctuation? - if((flags2[index] & 1) == 0) { - // skip - X++; - continue; - } - - // hold index - loopIndex = X; - - // Loop backwards from this point - pos48644: - - // back up one phoneme - X--; - - // stop once the beginning is reached - if(X == 0) break; - - // get the preceding phoneme - index = phonemeindex[X]; - - if(index != 255) //inserted to prevent access overrun - if((flags[index] & 128) == 0) goto pos48644; // if not a vowel, continue looping - - //pos48657: - do { - // test for vowel - index = phonemeindex[X]; - - if(index != 255) //inserted to prevent access overrun - // test for fricative/unvoiced or not voiced - if(((flags2[index] & 32) == 0) || ((flags[index] & 4) != 0)) //nochmal �berpr�fen - { - //A = flags[Y] & 4; - //if(A == 0) goto pos48688; - - // get the phoneme length - A = phonemeLength[X]; - - // change phoneme length to (length * 1.5) + 1 - A = (A >> 1) + A + 1; - - phonemeLength[X] = A; - } - // keep moving forward - X++; - } while(X != loopIndex); - // if (X != loopIndex) goto pos48657; - X++; - } // while - - // Similar to the above routine, but shorten vowels under some circumstances - - // Loop throught all phonemes - loopIndex = 0; - //pos48697 - - while(1) { - // get a phoneme - X = loopIndex; - index = phonemeindex[X]; - - // exit routine at end token - if(index == 255) return; - - // vowel? - A = flags[index] & 128; - if(A != 0) { - // get next phoneme - X++; - index = phonemeindex[X]; - - // get flags - if(index == 255) - mem56 = 65; // use if end marker - else - mem56 = flags[index]; - - // not a consonant - if((flags[index] & 64) == 0) { - // RX or LX? - if((index == 18) || (index == 19)) // 'RX' & 'LX' - { - // get the next phoneme - X++; - index = phonemeindex[X]; - - // next phoneme a consonant? - if((flags[index] & 64) != 0) { - // RULE: RX | LX - - // decrease length of vowel by 1 frame - phonemeLength[loopIndex]--; - } - // move ahead - loopIndex++; - continue; - } - // move ahead - loopIndex++; - continue; - } - - // Got here if not - - // not voiced - if((mem56 & 4) == 0) { - // Unvoiced - // *, .*, ?*, ,*, -*, DX, S*, SH, F*, TH, /H, /X, CH, P*, T*, K*, KX - - // not an unvoiced plosive? - if((mem56 & 1) == 0) { - // move ahead - loopIndex++; - continue; - } - - // P*, T*, K*, KX - - // RULE: - // - - // move back - X--; - - // decrease length by 1/8th - mem56 = phonemeLength[X] >> 3; - phonemeLength[X] -= mem56; - - // move ahead - loopIndex++; - continue; - } - - // RULE: - // - - // decrease length - A = phonemeLength[X - 1]; - phonemeLength[X - 1] = (A >> 2) + A + 1; // 5/4*A + 1 - - // move ahead - loopIndex++; - continue; - } - - // WH, R*, L*, W*, Y*, M*, N*, NX, Q*, Z*, ZH, V*, DH, J*, B*, D*, G*, GX - - //pos48821: - - // RULE: - // Set punctuation length to 6 - // Set stop consonant length to 5 - - // nasal? - if((flags2[index] & 8) != 0) { - // M*, N*, NX, - - // get the next phoneme - X++; - index = phonemeindex[X]; - - // end of buffer? - if(index == 255) - A = 65 & 2; //prevent buffer overflow - else - A = flags[index] & 2; // check for stop consonant - - // is next phoneme a stop consonant? - if(A != 0) - - // B*, D*, G*, GX, P*, T*, K*, KX - - { - // set stop consonant length to 6 - phonemeLength[X] = 6; - - // set nasal length to 5 - phonemeLength[X - 1] = 5; - } - // move to next phoneme - loopIndex++; - continue; - } - - // WH, R*, L*, W*, Y*, Q*, Z*, ZH, V*, DH, J*, B*, D*, G*, GX - - // RULE: {optional silence} - // Shorten both to (length/2 + 1) - - // (voiced) stop consonant? - if((flags[index] & 2) != 0) { - // B*, D*, G*, GX - - // move past silence - do { - // move ahead - X++; - index = phonemeindex[X]; - } while(index == 0); - - // check for end of buffer - if(index == 255) //buffer overflow - { - // ignore, overflow code - if((65 & 2) == 0) { - loopIndex++; - continue; - } - } else if((flags[index] & 2) == 0) { - // if another stop consonant, move ahead - loopIndex++; - continue; - } - - // RULE: {optional silence} - - // X gets overwritten, so hold prior X value for debug statement - // int debugX = X; - // shorten the prior phoneme length to (length/2 + 1) - phonemeLength[X] = (phonemeLength[X] >> 1) + 1; - X = loopIndex; - - // also shorten this phoneme length to (length/2 +1) - phonemeLength[loopIndex] = (phonemeLength[loopIndex] >> 1) + 1; - - // move ahead - loopIndex++; - continue; - } - - // WH, R*, L*, W*, Y*, Q*, Z*, ZH, V*, DH, J*, **, - - // RULE: - // Decrease by 2 - - // liquic consonant? - if((flags2[index] & 16) != 0) { - // R*, L*, W*, Y* - - // get the prior phoneme - index = phonemeindex[X - 1]; - - // prior phoneme a stop consonant> - if((flags[index] & 2) != 0) { - // Rule: - - // decrease the phoneme length by 2 frames (20 ms) - phonemeLength[X] -= 2; - } - } - - // move to next phoneme - loopIndex++; - continue; - } - // goto pos48701; -} - -// ------------------------------------------------------------------------- -// ML : Code47503 is division with remainder, and mem50 gets the sign -void STM32SAM::Code47503(unsigned char mem52) { - Y = 0; - if((mem53 & 128) != 0) { - mem53 = -mem53; - Y = 128; - } - mem50 = Y; - A = 0; - for(X = 8; X > 0; X--) { - int temp = mem53; - mem53 = mem53 << 1; - A = A << 1; - if(temp >= 128) A++; - if(A >= mem52) { - A = A - mem52; - mem53++; - } - } - - mem51 = A; - if((mem50 & 128) != 0) mem53 = -mem53; -} - -//////////////////////////////////////////////////////////////////////////////////////////// -// -// Reciter -// -//////////////////////////////////////////////////////////////////////////////////////////// - -void STM32SAM::Code37055(unsigned char mem59) { - X = mem59; - X--; - A = inputtemp[X]; - Y = A; - A = tab36376[Y]; - return; -} - -void STM32SAM::Code37066(unsigned char mem58) { - X = mem58; - X++; - A = inputtemp[X]; - Y = A; - A = tab36376[Y]; -} - -unsigned char STM32SAM::GetRuleByte(unsigned short mem62, unsigned char Y) { - unsigned int address = mem62; - - if(mem62 >= 37541) { - address -= 37541; - return rules2[address + Y]; - } - address -= 32000; - return rules[address + Y]; -} - -int STM32SAM::TextToPhonemes(unsigned char* input) // Code36484 -{ - //unsigned char *tab39445 = &mem[39445]; //input and output - //unsigned char mem29; - unsigned char mem56; //output position for phonemes - unsigned char mem57; - unsigned char mem58; - unsigned char mem59; - unsigned char mem60; - unsigned char mem61; - unsigned short mem62; // memory position of current rule - - unsigned char mem64; // position of '=' or current character - unsigned char mem65; // position of ')' - unsigned char mem66; // position of '(' - unsigned char mem36653; - - inputtemp[0] = 32; - - // secure copy of input - // because input will be overwritten by phonemes - X = 1; - Y = 0; - do { - //pos36499: - A = input[Y] & 127; - if(A >= 112) - A = A & 95; - else if(A >= 96) - A = A & 79; - - inputtemp[X] = A; - X++; - Y++; - } while(Y != 255); - - X = 255; - inputtemp[X] = 27; - mem61 = 255; - -pos36550: - A = 255; - mem56 = 255; - -pos36554: - while(1) { - mem61++; - X = mem61; - A = inputtemp[X]; - mem64 = A; - if(A == '[') { - mem56++; - X = mem56; - A = 155; - input[X] = 155; - //goto pos36542; - // Code39771(); //Code39777(); - return 1; - } - - //pos36579: - if(A != '.') break; - X++; - Y = inputtemp[X]; - A = tab36376[Y] & 1; - if(A != 0) break; - mem56++; - X = mem56; - A = '.'; - input[X] = '.'; - } //while - - //pos36607: - A = mem64; - Y = A; - A = tab36376[A]; - mem57 = A; - if((A & 2) != 0) { - mem62 = 37541; - goto pos36700; - } - - //pos36630: - A = mem57; - if(A != 0) goto pos36677; - A = 32; - inputtemp[X] = ' '; - mem56++; - X = mem56; - if(X > 120) goto pos36654; - input[X] = A; - goto pos36554; - - // ----- - - //36653 is unknown. Contains position - -pos36654: - input[X] = 155; - A = mem61; - mem36653 = A; - // mem29 = A; // not used - // Code36538(); das ist eigentlich - return 1; - //Code39771(); - //go on if there is more input ??? - mem61 = mem36653; - goto pos36550; - -pos36677: - A = mem57 & 128; - if(A == 0) { - //36683: BRK - return 0; - } - - // go to the right rules for this character. - X = mem64 - 'A'; - mem62 = tab37489[X] | (tab37515[X] << 8); - - // ------------------------------------- - // go to next rule - // ------------------------------------- - -pos36700: - - // find next rule - Y = 0; - do { - mem62 += 1; - A = GetRuleByte(mem62, Y); - } while((A & 128) == 0); - Y++; - - //pos36720: - // find '(' - while(1) { - A = GetRuleByte(mem62, Y); - if(A == '(') break; - Y++; - } - mem66 = Y; - - //pos36732: - // find ')' - do { - Y++; - A = GetRuleByte(mem62, Y); - } while(A != ')'); - mem65 = Y; - - //pos36741: - // find '=' - do { - Y++; - A = GetRuleByte(mem62, Y); - A = A & 127; - } while(A != '='); - mem64 = Y; - - X = mem61; - mem60 = X; - - // compare the string within the bracket - Y = mem66; - Y++; - //pos36759: - while(1) { - mem57 = inputtemp[X]; - A = GetRuleByte(mem62, Y); - if(A != mem57) goto pos36700; - Y++; - if(Y == mem65) break; - X++; - mem60 = X; - } - - // the string in the bracket is correct - - //pos36787: - A = mem61; - mem59 = mem61; - -pos36791: - while(1) { - mem66--; - Y = mem66; - A = GetRuleByte(mem62, Y); - mem57 = A; - //36800: BPL 36805 - if((A & 128) != 0) goto pos37180; - X = A & 127; - A = tab36376[X] & 128; - if(A == 0) break; - X = mem59 - 1; - A = inputtemp[X]; - if(A != mem57) goto pos36700; - mem59 = X; - } - - //pos36833: - A = mem57; - if(A == ' ') goto pos36895; - if(A == '#') goto pos36910; - if(A == '.') goto pos36920; - if(A == '&') goto pos36935; - if(A == '@') goto pos36967; - if(A == '^') goto pos37004; - if(A == '+') goto pos37019; - if(A == ':') goto pos37040; - // Code42041(); //Error - //36894: BRK - return 0; - - // -------------- - -pos36895: - Code37055(mem59); - A = A & 128; - if(A != 0) goto pos36700; -pos36905: - mem59 = X; - goto pos36791; - - // -------------- - -pos36910: - Code37055(mem59); - A = A & 64; - if(A != 0) goto pos36905; - goto pos36700; - - // -------------- - -pos36920: - Code37055(mem59); - A = A & 8; - if(A == 0) goto pos36700; -pos36930: - mem59 = X; - goto pos36791; - - // -------------- - -pos36935: - Code37055(mem59); - A = A & 16; - if(A != 0) goto pos36930; - A = inputtemp[X]; - if(A != 72) goto pos36700; - X--; - A = inputtemp[X]; - if((A == 67) || (A == 83)) goto pos36930; - goto pos36700; - - // -------------- - -pos36967: - Code37055(mem59); - A = A & 4; - if(A != 0) goto pos36930; - A = inputtemp[X]; - if(A != 72) goto pos36700; - if((A != 84) && (A != 67) && (A != 83)) goto pos36700; - mem59 = X; - goto pos36791; - - // -------------- - -pos37004: - Code37055(mem59); - A = A & 32; - if(A == 0) goto pos36700; - -pos37014: - mem59 = X; - goto pos36791; - - // -------------- - -pos37019: - X = mem59; - X--; - A = inputtemp[X]; - if((A == 'E') || (A == 'I') || (A == 'Y')) goto pos37014; - goto pos36700; - // -------------- - -pos37040: - Code37055(mem59); - A = A & 32; - if(A == 0) goto pos36791; - mem59 = X; - goto pos37040; - - //--------------------------------------- - -pos37077: - X = mem58 + 1; - A = inputtemp[X]; - if(A != 'E') goto pos37157; - X++; - Y = inputtemp[X]; - X--; - A = tab36376[Y] & 128; - if(A == 0) goto pos37108; - X++; - A = inputtemp[X]; - if(A != 'R') goto pos37113; -pos37108: - mem58 = X; - goto pos37184; -pos37113: - if((A == 83) || (A == 68)) goto pos37108; // 'S' 'D' - if(A != 76) goto pos37135; // 'L' - X++; - A = inputtemp[X]; - if(A != 89) goto pos36700; - goto pos37108; - -pos37135: - if(A != 70) goto pos36700; - X++; - A = inputtemp[X]; - if(A != 85) goto pos36700; - X++; - A = inputtemp[X]; - if(A == 76) goto pos37108; - goto pos36700; - -pos37157: - if(A != 73) goto pos36700; - X++; - A = inputtemp[X]; - if(A != 78) goto pos36700; - X++; - A = inputtemp[X]; - if(A == 71) goto pos37108; - //pos37177: - goto pos36700; - - // ----------------------------------------- - -pos37180: - - A = mem60; - mem58 = A; - -pos37184: - Y = mem65 + 1; - - //37187: CPY 64 - // if(? != 0) goto pos37194; - if(Y == mem64) goto pos37455; - mem65 = Y; - //37196: LDA (62),y - A = GetRuleByte(mem62, Y); - mem57 = A; - X = A; - A = tab36376[X] & 128; - if(A == 0) goto pos37226; - X = mem58 + 1; - A = inputtemp[X]; - if(A != mem57) goto pos36700; - mem58 = X; - goto pos37184; -pos37226: - A = mem57; - if(A == 32) goto pos37295; // ' ' - if(A == 35) goto pos37310; // '#' - if(A == 46) goto pos37320; // '.' - if(A == 38) goto pos37335; // '&' - if(A == 64) goto pos37367; // '' - if(A == 94) goto pos37404; // '' - if(A == 43) goto pos37419; // '+' - if(A == 58) goto pos37440; // ':' - if(A == 37) goto pos37077; // '%' - //pos37291: - // Code42041(); //Error - //37294: BRK - return 0; - - // -------------- -pos37295: - Code37066(mem58); - A = A & 128; - if(A != 0) goto pos36700; -pos37305: - mem58 = X; - goto pos37184; - - // -------------- - -pos37310: - Code37066(mem58); - A = A & 64; - if(A != 0) goto pos37305; - goto pos36700; - - // -------------- - -pos37320: - Code37066(mem58); - A = A & 8; - if(A == 0) goto pos36700; - -pos37330: - mem58 = X; - goto pos37184; - - // -------------- - -pos37335: - Code37066(mem58); - A = A & 16; - if(A != 0) goto pos37330; - A = inputtemp[X]; - if(A != 72) goto pos36700; - X++; - A = inputtemp[X]; - if((A == 67) || (A == 83)) goto pos37330; - goto pos36700; - - // -------------- - -pos37367: - Code37066(mem58); - A = A & 4; - if(A != 0) goto pos37330; - A = inputtemp[X]; - if(A != 72) goto pos36700; - if((A != 84) && (A != 67) && (A != 83)) goto pos36700; - mem58 = X; - goto pos37184; - - // -------------- - -pos37404: - Code37066(mem58); - A = A & 32; - if(A == 0) goto pos36700; -pos37414: - mem58 = X; - goto pos37184; - - // -------------- - -pos37419: - X = mem58; - X++; - A = inputtemp[X]; - if((A == 69) || (A == 73) || (A == 89)) goto pos37414; - goto pos36700; - - // ---------------------- - -pos37440: - - Code37066(mem58); - A = A & 32; - if(A == 0) goto pos37184; - mem58 = X; - goto pos37440; -pos37455: - Y = mem64; - mem61 = mem60; - -pos37461: - //37461: LDA (62),y - A = GetRuleByte(mem62, Y); - mem57 = A; - A = A & 127; - if(A != '=') { - mem56++; - X = mem56; - input[X] = A; - } - - //37478: BIT 57 - //37480: BPL 37485 //not negative flag - if((mem57 & 128) == 0) goto pos37485; //??? - goto pos36554; -pos37485: - Y++; - goto pos37461; -} - -// Constructor - -STM32SAM::STM32SAM(uint32_t STM32SAM_SPEED /* = 5 */) { - STM32SAM_SPEED = STM32SAM_SPEED & 0x1f; // limit it from 0 to 31 - - _STM32SAM_SPEED = STM32SAM_SPEED; - - // set default voice - - speed = 72; - pitch = 64; - mouth = 128; - throat = 128; - - phonetic = 0; - singmode = 0; - - wait1 = 7; - wait2 = 6; - - mem59 = 0; - - oldtimetableindex = 0; -} - -STM32SAM::STM32SAM() { - _STM32SAM_SPEED = 7; - - // set default voice - - speed = 72; - pitch = 64; - mouth = 128; - throat = 128; - - phonetic = 0; - singmode = 0; - - wait1 = 7; - wait2 = 6; - - mem59 = 0; - - oldtimetableindex = 0; -} - -/* - STM32SAM::~STM32SAM() { - { - // TODO: end(); - } -*/ - -//////////////////////////////////////////////////////////////////////////////////////////// -// -// STM32SAM sam (variable string, phonetic, sing, pitch, speed, mouth, throat) -// STM32SAM say (sing off, phonetic off) (const string) -// STM32SAM say (sing off, phonetic off) (variable string) -// STM32SAM sing (sing on, phonetic off) (const string) -// STM32SAM sing (sing on, phonetic off) (variable string) -// STM32SAM sayPhonetic (sing off, phonetic on) (const string) -// STM32SAM sayPhonetic (sing off, phonetic on) (variable string) -// STM32SAM singPhonetic (sing on, phonetic on) (const string) -// STM32SAM singPhonetic (sing on, phonetic on) (variable string) -// STM32SAM voice (pitch, speed, mouth, throat) -// STM32SAM setPitch (pitch) -// STM32SAM setSpeed (speed) -// STM32SAM setMouth (mouth) -// STM32SAM setThroat (throat) -// -// -//////////////////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////////////////// -// -// STM32SAM sam (const string, phonetic, sing, pitch, speed, mouth, throat) -// -//////////////////////////////////////////////////////////////////////////////////////////// - -char to_upper_case(char c) { - if(c >= 'a' && c <= 'z') { - return c - 'a' + 'A'; - } - return c; -} - -void STM32SAM::sam( - const char* argv, - unsigned char _phonetic, - unsigned char _singmode, - unsigned char _pitch, - unsigned char _speed, - unsigned char _mouth, - unsigned char _throat) { - phonetic = _phonetic; - singmode = _singmode; - pitch = _pitch; - speed = _speed; - mouth = _mouth; - throat = _throat; - - int i; - - for(i = 0; i < 256; i++) { - input[i] = argv[i]; - } - - for(i = 0; input[i] != 0; i++) { - if(i != 0) { - input[i] = to_upper_case((int)argv[i]); - } - } - - if(!phonetic) { - strncat(input, "[", 256); - if(!TextToPhonemes((unsigned char*)input)) { - // PrintUsage(); - return; - } - - } else { - strncat(input, "\x9b", 256); - } - - SetInput(input); - - if(!SAMMain()) { - return; - } -} - -//////////////////////////////////////////////////////////////////////////////////////////// -// -// STM32SAM sam (variable string, phonetic, sing, pitch, speed, mouth, throat) -// -//////////////////////////////////////////////////////////////////////////////////////////// - -void STM32SAM::sam( - char* argv, - unsigned char _phonetic, - unsigned char _singmode, - unsigned char _pitch, - unsigned char _speed, - unsigned char _mouth, - unsigned char _throat) { - phonetic = _phonetic; - singmode = _singmode; - pitch = _pitch; - speed = _speed; - mouth = _mouth; - throat = _throat; - - int i; - - for(i = 0; i < 256; i++) { - input[i] = argv[i]; - } - - for(i = 0; input[i] != 0; i++) { - if(i != 0) { - input[i] = to_upper_case((int)argv[i]); - } - } - - if(i < 256) { - input[i] = phonetic ? '\x9b' : '['; - } - - if(!phonetic) { - if(!TextToPhonemes((unsigned char*)input)) { - return; - } - } - - SetInput(input); - - if(!SAMMain()) { - return; - } -} - -//////////////////////////////////////////////////////////////////////////////////////////// -// -// STM32SAM say(sing off, phonetic off) (const string) -// -//////////////////////////////////////////////////////////////////////////////////////////// - -void STM32SAM::say(const char* argv) { - int i; - - phonetic = 0; - singmode = 0; - - char const_input[256]; - - for(i = 0; i < 256; i++) { - const_input[i] = argv[i]; - } - - sam(const_input, phonetic, singmode, pitch, speed, mouth, throat); -} - -void STM32SAM::say(char* argv) { - int i; - - phonetic = 0; - singmode = 0; - - char const_input[256]; - - for(i = 0; i < 256; i++) { - const_input[i] = argv[i]; - } - - sam(const_input, phonetic, singmode, pitch, speed, mouth, throat); -} - -//////////////////////////////////////////////////////////////////////////////////////////// -// -// STM32SAM sing (sing on, phonetic off) -// -//////////////////////////////////////////////////////////////////////////////////////////// - -void STM32SAM::sing(const char* argv) { - int i; - - phonetic = 0; - singmode = 1; - - char const_input[256]; - - for(i = 0; i < 256; i++) { - const_input[i] = argv[i]; - } - - sam(const_input, phonetic, singmode, pitch, speed, mouth, throat); -} - -void STM32SAM::sing(char* argv) { - int i; - - phonetic = 0; - singmode = 1; - - char const_input[256]; - - for(i = 0; i < 256; i++) { - const_input[i] = argv[i]; - } - - sam(const_input, phonetic, singmode, pitch, speed, mouth, throat); -} - -//////////////////////////////////////////////////////////////////////////////////////////// -// -// STM32SAM sayPhonetic (sing off, phonetic on) -// -//////////////////////////////////////////////////////////////////////////////////////////// - -void STM32SAM::sayPhonetic(const char* argv) { - int i; - - phonetic = 1; - singmode = 0; - - char const_input[256]; - - for(i = 0; i < 256; i++) { - const_input[i] = argv[i]; - } - - sam(const_input, phonetic, singmode, pitch, speed, mouth, throat); -} - -void STM32SAM::sayPhonetic(char* argv) { - int i; - - phonetic = 1; - singmode = 0; - - char const_input[256]; - - for(i = 0; i < 256; i++) { - const_input[i] = argv[i]; - } - - sam(const_input, phonetic, singmode, pitch, speed, mouth, throat); -} - -//////////////////////////////////////////////////////////////////////////////////////////// -// -// STM32SAM singPhonetic (sing on, phonetic on) -// -//////////////////////////////////////////////////////////////////////////////////////////// - -void STM32SAM::singPhonetic(const char* argv) { - int i; - - phonetic = 1; - singmode = 1; - - char const_input[256]; - - for(i = 0; i < 256; i++) { - const_input[i] = argv[i]; - } - - sam(const_input, phonetic, singmode, pitch, speed, mouth, throat); -} - -void STM32SAM::singPhonetic(char* argv) { - int i; - - phonetic = 1; - singmode = 0; - - char const_input[256]; - - for(i = 0; i < 256; i++) { - const_input[i] = argv[i]; - } - - sam(const_input, phonetic, singmode, pitch, speed, mouth, throat); -} - -//////////////////////////////////////////////////////////////////////////////////////////// -// -// STM32SAM voice (pitch, speed, mouth, throat) -// -//////////////////////////////////////////////////////////////////////////////////////////// - -void STM32SAM::setVoice( - unsigned char _pitch /* = 64 */, - unsigned char _speed /* = 72 */, - unsigned char _mouth /* = 128 */, - unsigned char _throat /* = 128 */) { - pitch = _pitch; - speed = _speed; - mouth = _mouth; - throat = _throat; -} - -//////////////////////////////////////////////////////////////////////////////////////////// -// -// STM32SAM setPitch (pitch) -// -//////////////////////////////////////////////////////////////////////////////////////////// - -void STM32SAM::setPitch(unsigned char _pitch /* = 64 */) { - pitch = _pitch; -} -//////////////////////////////////////////////////////////////////////////////////////////// -// -// STM32SAM setSpeed (speed) -// -//////////////////////////////////////////////////////////////////////////////////////////// - -void STM32SAM::setSpeed(unsigned char _speed /* = 72 */) { - speed = _speed; -} -//////////////////////////////////////////////////////////////////////////////////////////// -// -// STM32SAM setMouth (mouth) -// -//////////////////////////////////////////////////////////////////////////////////////////// - -void STM32SAM::setMouth(unsigned char _mouth /* = 128 */) { - mouth = _mouth; -} - -//////////////////////////////////////////////////////////////////////////////////////////// -// -// STM32SAM setThroat (throat) -// -//////////////////////////////////////////////////////////////////////////////////////////// - -void STM32SAM::setThroat(unsigned char _throat /* = 128 */) { - throat = _throat; -} -//////////////////////////////////////////////////////////////////////////////////////////// -// -// Hardware -// -//////////////////////////////////////////////////////////////////////////////////////////// -// Hardware specifics, for easier porting to other microcontrollers - -// -// Set PA8 pin as PWM, at 256 timer ticks overflow (8bit resolution) - -#include -#include - -#define FURI_HAL_SPEAKER_TIMER TIM16 -#define FURI_HAL_SPEAKER_CHANNEL LL_TIM_CHANNEL_CH1 - -void STM32SAM::begin(void) { -#ifdef USE_ROGER_CORE - - pinMode(PA8, PWM); // audio output pin - - Timer1.setPeriod( - 4); // Can't set at 256 ticks, only in uS. First nearest uS is 4 (Roger core is only for bluepill, that means 72*4=288 ticks, or 128*4=512 ticks when overclocked. It's ok, just overall volume will be lower, because maximum volume will be 256/288 or 256/512) - -#endif - -#ifdef USE_STM32duino_CORE - pinMode(PA8, OUTPUT); - - PWM->pause(); - PWM->setMode(1, TIMER_OUTPUT_COMPARE_PWM1, PA8); // TIM1 CH1 (PA8) - PWM->setPrescaleFactor(1); - PWM->setOverflow(256, TICK_FORMAT); // 256 ticks overflow, no matter the CPU (timer) speed - PWM->resume(); - -#endif - - LL_TIM_InitTypeDef TIM_InitStruct; - memset(&TIM_InitStruct, 0, sizeof(LL_TIM_InitTypeDef)); - TIM_InitStruct.Prescaler = 4; - TIM_InitStruct.Autoreload = 255; - LL_TIM_Init(FURI_HAL_SPEAKER_TIMER, &TIM_InitStruct); - - LL_TIM_OC_InitTypeDef TIM_OC_InitStruct; - memset(&TIM_OC_InitStruct, 0, sizeof(LL_TIM_OC_InitTypeDef)); - TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1; - TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE; - TIM_OC_InitStruct.CompareValue = 127; - LL_TIM_OC_Init(FURI_HAL_SPEAKER_TIMER, FURI_HAL_SPEAKER_CHANNEL, &TIM_OC_InitStruct); - - LL_TIM_EnableAllOutputs(FURI_HAL_SPEAKER_TIMER); - LL_TIM_EnableCounter(FURI_HAL_SPEAKER_TIMER); -} // begin - -inline void STM32SAM::SetAUDIO(unsigned char main_volume) { -#ifdef USE_ROGER_CORE - Timer1.setCompare(TIMER_CH1, main_volume); -#endif - -#ifdef USE_STM32duino_CORE - PWM->setCaptureCompare(1, main_volume, TICK_COMPARE_FORMAT); -#endif - - // if(main_volume > 64) { - // LL_TIM_OC_SetCompareCH1(FURI_HAL_SPEAKER_TIMER, 127); - // } else { - // LL_TIM_OC_SetCompareCH1(FURI_HAL_SPEAKER_TIMER, main_volume); - // } - - float data = main_volume; - data /= 255.0f; - data -= 0.5f; - data *= 4.0f; - data = tanhf(data); - - data += 0.5f; - data *= 255.0f; - - if(data < 0) { - data = 0; - } else if(data > 255) { - data = 255; - } - - LL_TIM_OC_SetCompareCH1(FURI_HAL_SPEAKER_TIMER, data); -} \ No newline at end of file diff --git a/applications/external/text2sam/stm32_sam.h b/applications/external/text2sam/stm32_sam.h deleted file mode 100644 index 910227ac3..000000000 --- a/applications/external/text2sam/stm32_sam.h +++ /dev/null @@ -1,96 +0,0 @@ -#include - -#ifndef __STM32SAM__ -#define __STM32SAM__ - -// SAM Text-To-Speech (TTS), ported from https://github.com/s-macke/SAM - -class STM32SAM { -public: - STM32SAM(uint32_t STM32SAM_SPEED); - STM32SAM(); - - void begin(void); - - void - sam(const char* argv, - unsigned char phonetic, - unsigned char singmode, - unsigned char pitch, - unsigned char speed, - unsigned char mouth, - unsigned char throat); - void - sam(char* argv, - unsigned char phonetic, - unsigned char singmode, - unsigned char pitch, - unsigned char speed, - unsigned char mouth, - unsigned char throat); - - void say(const char* argv); - void say(char* argv); - void sing(const char* argv); - void sing(char* argv); - void sayPhonetic(const char* argv); - void sayPhonetic(char* argv); - void singPhonetic(const char* argv); - void singPhonetic(char* argv); - void setVoice( - unsigned char _pitch = 64, - unsigned char _speed = 72, - unsigned char _mouth = 128, - unsigned char _throat = 128); - void setPitch(unsigned char _pitch = 64); - void setSpeed(unsigned char _speed = 72); - void setMouth(unsigned char _mouth = 128); - void setThroat(unsigned char _throat = 128); - -private: - void SetAUDIO(unsigned char main_volume); - - void Output8BitAry(int index, unsigned char ary[5]); - void Output8Bit(int index, unsigned char A); - unsigned char Read(unsigned char p, unsigned char Y); - void Write(unsigned char p, unsigned char Y, unsigned char value); - void RenderSample(unsigned char* mem66); - void Render(); - void AddInflection(unsigned char mem48, unsigned char phase1); - void SetMouthThroat(); - unsigned char trans(unsigned char mem39212, unsigned char mem39213); - void SetInput(char* _input); - void Init(); - int SAMMain(); - void PrepareOutput(); - void Insert( - unsigned char position /*var57*/, - unsigned char mem60, - unsigned char mem59, - unsigned char mem58); - void InsertBreath(); - void CopyStress(); - int Parser1(); - void SetPhonemeLength(); - void Code41240(); - void Parser2(); - void AdjustLengths(); - void Code47503(unsigned char mem52); - void Code37055(unsigned char mem59); - void Code37066(unsigned char mem58); - unsigned char GetRuleByte(unsigned short mem62, unsigned char Y); - int TextToPhonemes(unsigned char* input); // Code36484 - - uint32_t _STM32SAM_SPEED; - - unsigned char speed; - unsigned char pitch; - unsigned char mouth; - unsigned char throat; - - unsigned char phonetic; - unsigned char singmode; - -}; // STM32SAM class - -#endif \ No newline at end of file diff --git a/applications/external/uart_terminal/LICENSE b/applications/external/uart_terminal/LICENSE deleted file mode 100644 index c4613e7ea..000000000 --- a/applications/external/uart_terminal/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -MIT License - -Copyright (c) 2023 Malik cool4uma - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/applications/external/uart_terminal/application.fam b/applications/external/uart_terminal/application.fam deleted file mode 100644 index 1416c6d57..000000000 --- a/applications/external/uart_terminal/application.fam +++ /dev/null @@ -1,14 +0,0 @@ -App( - appid="uart_terminal", - name="[UART] UART Terminal", - apptype=FlipperAppType.EXTERNAL, - entry_point="uart_terminal_app", - requires=["gui"], - stack_size=1 * 1024, - fap_icon="uart_terminal.png", - fap_category="GPIO", - fap_icon_assets="assets", - fap_author="@cool4uma & (some fixes by @xMasterX)", - fap_version="1.1", - fap_description="Control various devices via the Flipper Zero UART interface.", -) diff --git a/applications/external/uart_terminal/scenes/uart_terminal_scene.c b/applications/external/uart_terminal/scenes/uart_terminal_scene.c deleted file mode 100644 index 451c5d98b..000000000 --- a/applications/external/uart_terminal/scenes/uart_terminal_scene.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "uart_terminal_scene.h" - -// Generate scene on_enter handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, -void (*const uart_terminal_scene_on_enter_handlers[])(void*) = { -#include "uart_terminal_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_event handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, -bool (*const uart_terminal_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = { -#include "uart_terminal_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_exit handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, -void (*const uart_terminal_scene_on_exit_handlers[])(void* context) = { -#include "uart_terminal_scene_config.h" -}; -#undef ADD_SCENE - -// Initialize scene handlers configuration structure -const SceneManagerHandlers uart_terminal_scene_handlers = { - .on_enter_handlers = uart_terminal_scene_on_enter_handlers, - .on_event_handlers = uart_terminal_scene_on_event_handlers, - .on_exit_handlers = uart_terminal_scene_on_exit_handlers, - .scene_num = UART_TerminalSceneNum, -}; diff --git a/applications/external/uart_terminal/scenes/uart_terminal_scene.h b/applications/external/uart_terminal/scenes/uart_terminal_scene.h deleted file mode 100644 index c6f4ed4b4..000000000 --- a/applications/external/uart_terminal/scenes/uart_terminal_scene.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -// Generate scene id and total number -#define ADD_SCENE(prefix, name, id) UART_TerminalScene##id, -typedef enum { -#include "uart_terminal_scene_config.h" - UART_TerminalSceneNum, -} UART_TerminalScene; -#undef ADD_SCENE - -extern const SceneManagerHandlers uart_terminal_scene_handlers; - -// Generate scene on_enter handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); -#include "uart_terminal_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_event handlers declaration -#define ADD_SCENE(prefix, name, id) \ - bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); -#include "uart_terminal_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_exit handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); -#include "uart_terminal_scene_config.h" -#undef ADD_SCENE diff --git a/applications/external/uart_terminal/scenes/uart_terminal_scene_config.h b/applications/external/uart_terminal/scenes/uart_terminal_scene_config.h deleted file mode 100644 index 51310800e..000000000 --- a/applications/external/uart_terminal/scenes/uart_terminal_scene_config.h +++ /dev/null @@ -1,3 +0,0 @@ -ADD_SCENE(uart_terminal, start, Start) -ADD_SCENE(uart_terminal, console_output, ConsoleOutput) -ADD_SCENE(uart_terminal, text_input, TextInput) diff --git a/applications/external/uart_terminal/scenes/uart_terminal_scene_console_output.c b/applications/external/uart_terminal/scenes/uart_terminal_scene_console_output.c deleted file mode 100644 index 6988c42de..000000000 --- a/applications/external/uart_terminal/scenes/uart_terminal_scene_console_output.c +++ /dev/null @@ -1,148 +0,0 @@ -#include "../uart_terminal_app_i.h" - -void uart_terminal_console_output_handle_rx_data_cb(uint8_t* buf, size_t len, void* context) { - furi_assert(context); - UART_TerminalApp* app = context; - - // If text box store gets too big, then truncate it - app->text_box_store_strlen += len; - if(app->text_box_store_strlen >= UART_TERMINAL_TEXT_BOX_STORE_SIZE - 1) { - furi_string_right(app->text_box_store, app->text_box_store_strlen / 2); - app->text_box_store_strlen = furi_string_size(app->text_box_store) + len; - } - - // Null-terminate buf and append to text box store - buf[len] = '\0'; - furi_string_cat_printf(app->text_box_store, "%s", buf); - - view_dispatcher_send_custom_event( - app->view_dispatcher, UART_TerminalEventRefreshConsoleOutput); -} - -void uart_terminal_scene_console_output_on_enter(void* context) { - UART_TerminalApp* app = context; - - TextBox* text_box = app->text_box; - text_box_reset(app->text_box); - text_box_set_font(text_box, TextBoxFontText); - if(app->focus_console_start) { - text_box_set_focus(text_box, TextBoxFocusStart); - } else { - text_box_set_focus(text_box, TextBoxFocusEnd); - } - - //Change baudrate /////////////////////////////////////////////////////////////////////////// - if(0 == strncmp("2400", app->selected_tx_string, strlen("2400")) && app->BAUDRATE != 2400) { - uart_terminal_uart_free(app->uart); - app->BAUDRATE = 2400; - app->uart = uart_terminal_uart_init(app); - } - if(0 == strncmp("9600", app->selected_tx_string, strlen("9600")) && app->BAUDRATE != 9600) { - uart_terminal_uart_free(app->uart); - app->BAUDRATE = 9600; - app->uart = uart_terminal_uart_init(app); - } - if(0 == strncmp("19200", app->selected_tx_string, strlen("19200")) && app->BAUDRATE != 19200) { - uart_terminal_uart_free(app->uart); - app->BAUDRATE = 19200; - app->uart = uart_terminal_uart_init(app); - } - if(0 == strncmp("38400", app->selected_tx_string, strlen("38400")) && app->BAUDRATE != 38400) { - uart_terminal_uart_free(app->uart); - app->BAUDRATE = 38400; - app->uart = uart_terminal_uart_init(app); - } - if(0 == strncmp("57600", app->selected_tx_string, strlen("57600")) && app->BAUDRATE != 57600) { - uart_terminal_uart_free(app->uart); - app->BAUDRATE = 57600; - app->uart = uart_terminal_uart_init(app); - } - if(0 == strncmp("115200", app->selected_tx_string, strlen("115200")) && - app->BAUDRATE != 115200) { - uart_terminal_uart_free(app->uart); - app->BAUDRATE = 115200; - app->uart = uart_terminal_uart_init(app); - } - if(0 == strncmp("230400", app->selected_tx_string, strlen("230400")) && - app->BAUDRATE != 230400) { - uart_terminal_uart_free(app->uart); - app->BAUDRATE = 230400; - app->uart = uart_terminal_uart_init(app); - } - if(0 == strncmp("460800", app->selected_tx_string, strlen("460800")) && - app->BAUDRATE != 460800) { - uart_terminal_uart_free(app->uart); - app->BAUDRATE = 460800; - app->uart = uart_terminal_uart_init(app); - } - if(0 == strncmp("921600", app->selected_tx_string, strlen("921600")) && - app->BAUDRATE != 921600) { - uart_terminal_uart_free(app->uart); - app->BAUDRATE = 921600; - app->uart = uart_terminal_uart_init(app); - } - ///////////////////////////////////////////////////////////////////////////////////////////////////// - - if(app->is_command) { - furi_string_reset(app->text_box_store); - app->text_box_store_strlen = 0; - - if(0 == strncmp("help", app->selected_tx_string, strlen("help"))) { - const char* help_msg = - "UART terminal for Flipper\n\nI'm in github: cool4uma\n\nThis app is a modified\nWiFi Marauder companion,\nThanks 0xchocolate(github)\nfor great code and app.\n\n"; - furi_string_cat_str(app->text_box_store, help_msg); - app->text_box_store_strlen += strlen(help_msg); - } - - if(app->show_stopscan_tip) { - const char* help_msg = "Press BACK to return\n"; - furi_string_cat_str(app->text_box_store, help_msg); - app->text_box_store_strlen += strlen(help_msg); - } - } - - // Set starting text - for "View Log", this will just be what was already in the text box store - text_box_set_text(app->text_box, furi_string_get_cstr(app->text_box_store)); - - scene_manager_set_scene_state(app->scene_manager, UART_TerminalSceneConsoleOutput, 0); - view_dispatcher_switch_to_view(app->view_dispatcher, UART_TerminalAppViewConsoleOutput); - - // Register callback to receive data - uart_terminal_uart_set_handle_rx_data_cb( - app->uart, uart_terminal_console_output_handle_rx_data_cb); // setup callback for rx thread - - // Send command with CR+LF or newline '\n' - if(app->is_command && app->selected_tx_string) { - if(app->TERMINAL_MODE == 1) { - uart_terminal_uart_tx( - (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string)); - uart_terminal_uart_tx((uint8_t*)("\r\n"), 2); - } else { - uart_terminal_uart_tx( - (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string)); - uart_terminal_uart_tx((uint8_t*)("\n"), 1); - } - } -} - -bool uart_terminal_scene_console_output_on_event(void* context, SceneManagerEvent event) { - UART_TerminalApp* app = context; - - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - text_box_set_text(app->text_box, furi_string_get_cstr(app->text_box_store)); - consumed = true; - } else if(event.type == SceneManagerEventTypeTick) { - consumed = true; - } - - return consumed; -} - -void uart_terminal_scene_console_output_on_exit(void* context) { - UART_TerminalApp* app = context; - - // Unregister rx callback - uart_terminal_uart_set_handle_rx_data_cb(app->uart, NULL); -} \ No newline at end of file diff --git a/applications/external/uart_terminal/scenes/uart_terminal_scene_start.c b/applications/external/uart_terminal/scenes/uart_terminal_scene_start.c deleted file mode 100644 index 60411b34c..000000000 --- a/applications/external/uart_terminal/scenes/uart_terminal_scene_start.c +++ /dev/null @@ -1,138 +0,0 @@ -#include "../uart_terminal_app_i.h" - -// For each command, define whether additional arguments are needed -// (enabling text input to fill them out), and whether the console -// text box should focus at the start of the output or the end -typedef enum { NO_ARGS = 0, INPUT_ARGS, TOGGLE_ARGS } InputArgs; - -typedef enum { FOCUS_CONSOLE_END = 0, FOCUS_CONSOLE_START, FOCUS_CONSOLE_TOGGLE } FocusConsole; - -#define SHOW_STOPSCAN_TIP (true) -#define NO_TIP (false) - -#define MAX_OPTIONS (9) -typedef struct { - const char* item_string; - const char* options_menu[MAX_OPTIONS]; - int num_options_menu; - const char* actual_commands[MAX_OPTIONS]; - InputArgs needs_keyboard; - FocusConsole focus_console; - bool show_stopscan_tip; -} UART_TerminalItem; - -// NUM_MENU_ITEMS defined in uart_terminal_app_i.h - if you add an entry here, increment it! -const UART_TerminalItem items[NUM_MENU_ITEMS] = { - {"Console", - {"115200", "2400", "9600", "19200", "38400", "57600", "230400", "460800", "921600"}, - 9, - {"115200", "2400", "9600", "19200", "38400", "57600", "230400", "460800", "921600"}, - NO_ARGS, - FOCUS_CONSOLE_END, - NO_TIP}, - {"Send command", {""}, 1, {""}, INPUT_ARGS, FOCUS_CONSOLE_END, NO_TIP}, - {"Send AT command", {""}, 1, {"AT"}, INPUT_ARGS, FOCUS_CONSOLE_END, NO_TIP}, - {"Fast cmd", - {"help", "uptime", "date", "df -h", "ps", "dmesg", "reboot", "poweroff"}, - 8, - {"help", "uptime", "date", "df -h", "ps", "dmesg", "reboot", "poweroff"}, - INPUT_ARGS, - FOCUS_CONSOLE_END, - NO_TIP}, - {"Help", {""}, 1, {"help"}, NO_ARGS, FOCUS_CONSOLE_START, SHOW_STOPSCAN_TIP}, -}; - -static void uart_terminal_scene_start_var_list_enter_callback(void* context, uint32_t index) { - furi_assert(context); - UART_TerminalApp* app = context; - - furi_assert(index < NUM_MENU_ITEMS); - const UART_TerminalItem* item = &items[index]; - - const int selected_option_index = app->selected_option_index[index]; - furi_assert(selected_option_index < item->num_options_menu); - app->selected_tx_string = item->actual_commands[selected_option_index]; - app->is_command = (1 <= index); - app->is_custom_tx_string = false; - app->selected_menu_index = index; - app->focus_console_start = (item->focus_console == FOCUS_CONSOLE_TOGGLE) ? - (selected_option_index == 0) : - item->focus_console; - app->show_stopscan_tip = item->show_stopscan_tip; - - bool needs_keyboard = (item->needs_keyboard == TOGGLE_ARGS) ? (selected_option_index != 0) : - item->needs_keyboard; - if(needs_keyboard) { - view_dispatcher_send_custom_event(app->view_dispatcher, UART_TerminalEventStartKeyboard); - } else { - view_dispatcher_send_custom_event(app->view_dispatcher, UART_TerminalEventStartConsole); - } -} - -static void uart_terminal_scene_start_var_list_change_callback(VariableItem* item) { - furi_assert(item); - - UART_TerminalApp* app = variable_item_get_context(item); - furi_assert(app); - - const UART_TerminalItem* menu_item = &items[app->selected_menu_index]; - uint8_t item_index = variable_item_get_current_value_index(item); - furi_assert(item_index < menu_item->num_options_menu); - variable_item_set_current_value_text(item, menu_item->options_menu[item_index]); - app->selected_option_index[app->selected_menu_index] = item_index; -} - -void uart_terminal_scene_start_on_enter(void* context) { - UART_TerminalApp* app = context; - VariableItemList* var_item_list = app->var_item_list; - - variable_item_list_set_enter_callback( - var_item_list, uart_terminal_scene_start_var_list_enter_callback, app); - - VariableItem* item; - for(int i = 0; i < NUM_MENU_ITEMS; ++i) { - item = variable_item_list_add( - var_item_list, - items[i].item_string, - items[i].num_options_menu, - uart_terminal_scene_start_var_list_change_callback, - app); - variable_item_set_current_value_index(item, app->selected_option_index[i]); - variable_item_set_current_value_text( - item, items[i].options_menu[app->selected_option_index[i]]); - } - - variable_item_list_set_selected_item( - var_item_list, scene_manager_get_scene_state(app->scene_manager, UART_TerminalSceneStart)); - - view_dispatcher_switch_to_view(app->view_dispatcher, UART_TerminalAppViewVarItemList); -} - -bool uart_terminal_scene_start_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UART_TerminalApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == UART_TerminalEventStartKeyboard) { - scene_manager_set_scene_state( - app->scene_manager, UART_TerminalSceneStart, app->selected_menu_index); - scene_manager_next_scene(app->scene_manager, UART_TerminalAppViewTextInput); - } else if(event.event == UART_TerminalEventStartConsole) { - scene_manager_set_scene_state( - app->scene_manager, UART_TerminalSceneStart, app->selected_menu_index); - scene_manager_next_scene(app->scene_manager, UART_TerminalAppViewConsoleOutput); - } - consumed = true; - } else if(event.type == SceneManagerEventTypeTick) { - app->selected_menu_index = variable_item_list_get_selected_item_index(app->var_item_list); - consumed = true; - } - - return consumed; -} - -void uart_terminal_scene_start_on_exit(void* context) { - UART_TerminalApp* app = context; - variable_item_list_reset(app->var_item_list); -} diff --git a/applications/external/uart_terminal/scenes/uart_terminal_scene_text_input.c b/applications/external/uart_terminal/scenes/uart_terminal_scene_text_input.c deleted file mode 100644 index 5cd6e7472..000000000 --- a/applications/external/uart_terminal/scenes/uart_terminal_scene_text_input.c +++ /dev/null @@ -1,68 +0,0 @@ -#include "../uart_terminal_app_i.h" - -void uart_terminal_scene_text_input_callback(void* context) { - UART_TerminalApp* app = context; - - view_dispatcher_send_custom_event(app->view_dispatcher, UART_TerminalEventStartConsole); -} - -void uart_terminal_scene_text_input_on_enter(void* context) { - UART_TerminalApp* app = context; - - if(false == app->is_custom_tx_string) { - // Fill text input with selected string so that user can add to it - size_t length = strlen(app->selected_tx_string); - furi_assert(length < UART_TERMINAL_TEXT_INPUT_STORE_SIZE); - bzero(app->text_input_store, UART_TERMINAL_TEXT_INPUT_STORE_SIZE); - strncpy(app->text_input_store, app->selected_tx_string, length); - - // Add space - because flipper keyboard currently doesn't have a space - //app->text_input_store[length] = ' '; - app->text_input_store[length + 1] = '\0'; - app->is_custom_tx_string = true; - } - - // Setup view - TextInput* text_input = app->text_input; - // Add help message to header - if(0 == strncmp("AT", app->selected_tx_string, strlen("AT"))) { - app->TERMINAL_MODE = 1; - text_input_set_header_text(text_input, "Send AT command to UART"); - } else { - app->TERMINAL_MODE = 0; - text_input_set_header_text(text_input, "Send command to UART"); - } - text_input_set_result_callback( - text_input, - uart_terminal_scene_text_input_callback, - app, - app->text_input_store, - UART_TERMINAL_TEXT_INPUT_STORE_SIZE, - false); - - text_input_add_illegal_symbols(text_input); - - view_dispatcher_switch_to_view(app->view_dispatcher, UART_TerminalAppViewTextInput); -} - -bool uart_terminal_scene_text_input_on_event(void* context, SceneManagerEvent event) { - UART_TerminalApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == UART_TerminalEventStartConsole) { - // Point to custom string to send - app->selected_tx_string = app->text_input_store; - scene_manager_next_scene(app->scene_manager, UART_TerminalAppViewConsoleOutput); - consumed = true; - } - } - - return consumed; -} - -void uart_terminal_scene_text_input_on_exit(void* context) { - UART_TerminalApp* app = context; - - text_input_reset(app->text_input); -} diff --git a/applications/external/uart_terminal/uart_terminal.png b/applications/external/uart_terminal/uart_terminal.png deleted file mode 100644 index 8420f5692..000000000 Binary files a/applications/external/uart_terminal/uart_terminal.png and /dev/null differ diff --git a/applications/external/uart_terminal/uart_terminal_app.c b/applications/external/uart_terminal/uart_terminal_app.c deleted file mode 100644 index 006cbaff4..000000000 --- a/applications/external/uart_terminal/uart_terminal_app.c +++ /dev/null @@ -1,102 +0,0 @@ -#include "uart_terminal_app_i.h" - -#include -#include - -static bool uart_terminal_app_custom_event_callback(void* context, uint32_t event) { - furi_assert(context); - UART_TerminalApp* app = context; - return scene_manager_handle_custom_event(app->scene_manager, event); -} - -static bool uart_terminal_app_back_event_callback(void* context) { - furi_assert(context); - UART_TerminalApp* app = context; - return scene_manager_handle_back_event(app->scene_manager); -} - -static void uart_terminal_app_tick_event_callback(void* context) { - furi_assert(context); - UART_TerminalApp* app = context; - scene_manager_handle_tick_event(app->scene_manager); -} - -UART_TerminalApp* uart_terminal_app_alloc() { - UART_TerminalApp* app = malloc(sizeof(UART_TerminalApp)); - - app->gui = furi_record_open(RECORD_GUI); - - app->view_dispatcher = view_dispatcher_alloc(); - app->scene_manager = scene_manager_alloc(&uart_terminal_scene_handlers, app); - view_dispatcher_enable_queue(app->view_dispatcher); - view_dispatcher_set_event_callback_context(app->view_dispatcher, app); - - view_dispatcher_set_custom_event_callback( - app->view_dispatcher, uart_terminal_app_custom_event_callback); - view_dispatcher_set_navigation_event_callback( - app->view_dispatcher, uart_terminal_app_back_event_callback); - view_dispatcher_set_tick_event_callback( - app->view_dispatcher, uart_terminal_app_tick_event_callback, 100); - - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - - app->var_item_list = variable_item_list_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - UART_TerminalAppViewVarItemList, - variable_item_list_get_view(app->var_item_list)); - - for(int i = 0; i < NUM_MENU_ITEMS; ++i) { - app->selected_option_index[i] = 0; - } - - app->text_box = text_box_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, UART_TerminalAppViewConsoleOutput, text_box_get_view(app->text_box)); - app->text_box_store = furi_string_alloc(); - furi_string_reserve(app->text_box_store, UART_TERMINAL_TEXT_BOX_STORE_SIZE); - - app->text_input = text_input_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, UART_TerminalAppViewTextInput, text_input_get_view(app->text_input)); - - scene_manager_next_scene(app->scene_manager, UART_TerminalSceneStart); - - return app; -} - -void uart_terminal_app_free(UART_TerminalApp* app) { - furi_assert(app); - - // Views - view_dispatcher_remove_view(app->view_dispatcher, UART_TerminalAppViewVarItemList); - view_dispatcher_remove_view(app->view_dispatcher, UART_TerminalAppViewConsoleOutput); - view_dispatcher_remove_view(app->view_dispatcher, UART_TerminalAppViewTextInput); - text_box_free(app->text_box); - furi_string_free(app->text_box_store); - text_input_free(app->text_input); - - // View dispatcher - view_dispatcher_free(app->view_dispatcher); - scene_manager_free(app->scene_manager); - - uart_terminal_uart_free(app->uart); - - // Close records - furi_record_close(RECORD_GUI); - - free(app); -} - -int32_t uart_terminal_app(void* p) { - UNUSED(p); - UART_TerminalApp* uart_terminal_app = uart_terminal_app_alloc(); - - uart_terminal_app->uart = uart_terminal_uart_init(uart_terminal_app); - - view_dispatcher_run(uart_terminal_app->view_dispatcher); - - uart_terminal_app_free(uart_terminal_app); - - return 0; -} diff --git a/applications/external/uart_terminal/uart_terminal_app.h b/applications/external/uart_terminal/uart_terminal_app.h deleted file mode 100644 index c859d828b..000000000 --- a/applications/external/uart_terminal/uart_terminal_app.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct UART_TerminalApp UART_TerminalApp; - -#ifdef __cplusplus -} -#endif diff --git a/applications/external/uart_terminal/uart_terminal_app_i.h b/applications/external/uart_terminal/uart_terminal_app_i.h deleted file mode 100644 index 5d2e3078c..000000000 --- a/applications/external/uart_terminal/uart_terminal_app_i.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include "uart_terminal_app.h" -#include "scenes/uart_terminal_scene.h" -#include "uart_terminal_custom_event.h" -#include "uart_terminal_uart.h" - -#include -#include -#include -#include -#include -#include - -#include - -#define NUM_MENU_ITEMS (5) - -#define UART_TERMINAL_TEXT_BOX_STORE_SIZE (4096) -#define UART_TERMINAL_TEXT_INPUT_STORE_SIZE (512) -#define UART_CH \ - (XTREME_SETTINGS()->uart_general_channel == UARTDefault ? FuriHalUartIdUSART1 : \ - FuriHalUartIdLPUART1) - -struct UART_TerminalApp { - Gui* gui; - ViewDispatcher* view_dispatcher; - SceneManager* scene_manager; - - char text_input_store[UART_TERMINAL_TEXT_INPUT_STORE_SIZE + 1]; - FuriString* text_box_store; - size_t text_box_store_strlen; - TextBox* text_box; - TextInput* text_input; - - VariableItemList* var_item_list; - - UART_TerminalUart* uart; - int selected_menu_index; - int selected_option_index[NUM_MENU_ITEMS]; - const char* selected_tx_string; - bool is_command; - bool is_custom_tx_string; - bool focus_console_start; - bool show_stopscan_tip; - int BAUDRATE; - int TERMINAL_MODE; //1=AT mode, 0=other mode -}; - -typedef enum { - UART_TerminalAppViewVarItemList, - UART_TerminalAppViewConsoleOutput, - UART_TerminalAppViewTextInput, -} UART_TerminalAppView; diff --git a/applications/external/uart_terminal/uart_terminal_custom_event.h b/applications/external/uart_terminal/uart_terminal_custom_event.h deleted file mode 100644 index d57d822d1..000000000 --- a/applications/external/uart_terminal/uart_terminal_custom_event.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -typedef enum { - UART_TerminalEventRefreshConsoleOutput = 0, - UART_TerminalEventStartConsole, - UART_TerminalEventStartKeyboard, -} UART_TerminalCustomEvent; diff --git a/applications/external/uart_terminal/uart_terminal_uart.c b/applications/external/uart_terminal/uart_terminal_uart.c deleted file mode 100644 index b289987f5..000000000 --- a/applications/external/uart_terminal/uart_terminal_uart.c +++ /dev/null @@ -1,106 +0,0 @@ -#include "uart_terminal_app_i.h" -#include "uart_terminal_uart.h" - -//#define UART_CH (FuriHalUartIdUSART1) -//#define BAUDRATE (115200) - -struct UART_TerminalUart { - UART_TerminalApp* app; - FuriThread* rx_thread; - FuriStreamBuffer* rx_stream; - uint8_t rx_buf[RX_BUF_SIZE + 1]; - void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context); -}; - -typedef enum { - WorkerEvtStop = (1 << 0), - WorkerEvtRxDone = (1 << 1), -} WorkerEvtFlags; - -void uart_terminal_uart_set_handle_rx_data_cb( - UART_TerminalUart* uart, - void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context)) { - furi_assert(uart); - uart->handle_rx_data_cb = handle_rx_data_cb; -} - -#define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone) - -void uart_terminal_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) { - UART_TerminalUart* uart = (UART_TerminalUart*)context; - - if(ev == UartIrqEventRXNE) { - furi_stream_buffer_send(uart->rx_stream, &data, 1, 0); - furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtRxDone); - } -} - -static int32_t uart_worker(void* context) { - UART_TerminalUart* uart = (void*)context; - - while(1) { - uint32_t events = - furi_thread_flags_wait(WORKER_ALL_RX_EVENTS, FuriFlagWaitAny, FuriWaitForever); - furi_check((events & FuriFlagError) == 0); - if(events & WorkerEvtStop) break; - if(events & WorkerEvtRxDone) { - size_t len = furi_stream_buffer_receive(uart->rx_stream, uart->rx_buf, RX_BUF_SIZE, 0); - if(len > 0) { - if(uart->handle_rx_data_cb) uart->handle_rx_data_cb(uart->rx_buf, len, uart->app); - } - } - } - - furi_hal_uart_set_irq_cb(UART_CH, NULL, NULL); - furi_stream_buffer_free(uart->rx_stream); - - return 0; -} - -void uart_terminal_uart_tx(uint8_t* data, size_t len) { - furi_hal_uart_tx(UART_CH, data, len); -} - -UART_TerminalUart* uart_terminal_uart_init(UART_TerminalApp* app) { - UART_TerminalUart* uart = malloc(sizeof(UART_TerminalUart)); - uart->app = app; - // Init all rx stream and thread early to avoid crashes - uart->rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE, 1); - uart->rx_thread = furi_thread_alloc(); - furi_thread_set_name(uart->rx_thread, "UART_TerminalUartRxThread"); - furi_thread_set_stack_size(uart->rx_thread, 1024); - furi_thread_set_context(uart->rx_thread, uart); - furi_thread_set_callback(uart->rx_thread, uart_worker); - - furi_thread_start(uart->rx_thread); - - if(UART_CH == FuriHalUartIdUSART1) { - furi_hal_console_disable(); - } else if(UART_CH == FuriHalUartIdLPUART1) { - furi_hal_uart_init(UART_CH, app->BAUDRATE); - } - - if(app->BAUDRATE == 0) { - app->BAUDRATE = 115200; - } - furi_hal_uart_set_br(UART_CH, app->BAUDRATE); - furi_hal_uart_set_irq_cb(UART_CH, uart_terminal_uart_on_irq_cb, uart); - - return uart; -} - -void uart_terminal_uart_free(UART_TerminalUart* uart) { - furi_assert(uart); - - furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtStop); - furi_thread_join(uart->rx_thread); - furi_thread_free(uart->rx_thread); - - if(UART_CH == FuriHalUartIdLPUART1) { - furi_hal_uart_deinit(UART_CH); - } else { - furi_hal_console_enable(); - } - - free(uart); -} \ No newline at end of file diff --git a/applications/external/uart_terminal/uart_terminal_uart.h b/applications/external/uart_terminal/uart_terminal_uart.h deleted file mode 100644 index ca95c92fb..000000000 --- a/applications/external/uart_terminal/uart_terminal_uart.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "furi_hal.h" - -#define RX_BUF_SIZE (320) - -typedef struct UART_TerminalUart UART_TerminalUart; - -void uart_terminal_uart_set_handle_rx_data_cb( - UART_TerminalUart* uart, - void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context)); -void uart_terminal_uart_tx(uint8_t* data, size_t len); -UART_TerminalUart* uart_terminal_uart_init(UART_TerminalApp* app); -void uart_terminal_uart_free(UART_TerminalUart* uart); diff --git a/applications/external/uart_terminal/uart_validators.c b/applications/external/uart_terminal/uart_validators.c deleted file mode 100644 index c87a6cc6e..000000000 --- a/applications/external/uart_terminal/uart_validators.c +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include "uart_validators.h" -#include - -struct ValidatorIsFile { - char* app_path_folder; - const char* app_extension; - char* current_name; -}; - -bool validator_is_file_callback(const char* text, FuriString* error, void* context) { - furi_assert(context); - ValidatorIsFile* instance = context; - - if(instance->current_name != NULL) { - if(strcmp(instance->current_name, text) == 0) { - return true; - } - } - - bool ret = true; - FuriString* path = furi_string_alloc_printf( - "%s/%s%s", instance->app_path_folder, text, instance->app_extension); - Storage* storage = furi_record_open(RECORD_STORAGE); - if(storage_common_stat(storage, furi_string_get_cstr(path), NULL) == FSE_OK) { - ret = false; - furi_string_printf(error, "This name\nexists!\nChoose\nanother one."); - } else { - ret = true; - } - furi_string_free(path); - furi_record_close(RECORD_STORAGE); - - return ret; -} - -ValidatorIsFile* validator_is_file_alloc_init( - const char* app_path_folder, - const char* app_extension, - const char* current_name) { - ValidatorIsFile* instance = malloc(sizeof(ValidatorIsFile)); - - instance->app_path_folder = strdup(app_path_folder); - instance->app_extension = app_extension; - if(current_name != NULL) { - instance->current_name = strdup(current_name); - } - - return instance; -} - -void validator_is_file_free(ValidatorIsFile* instance) { - furi_assert(instance); - free(instance->app_path_folder); - free(instance->current_name); - free(instance); -} diff --git a/applications/external/uart_terminal/uart_validators.h b/applications/external/uart_terminal/uart_validators.h deleted file mode 100644 index d9200b6db..000000000 --- a/applications/external/uart_terminal/uart_validators.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include - -#ifdef __cplusplus -extern "C" { -#endif -typedef struct ValidatorIsFile ValidatorIsFile; - -ValidatorIsFile* validator_is_file_alloc_init( - const char* app_path_folder, - const char* app_extension, - const char* current_name); - -void validator_is_file_free(ValidatorIsFile* instance); - -bool validator_is_file_callback(const char* text, FuriString* error, void* context); - -#ifdef __cplusplus -} -#endif diff --git a/applications/external/wav_player/application.fam b/applications/external/wav_player/application.fam deleted file mode 100644 index 112add8ee..000000000 --- a/applications/external/wav_player/application.fam +++ /dev/null @@ -1,13 +0,0 @@ -App( - appid="wav_player", - name="WAV Player", - apptype=FlipperAppType.EXTERNAL, - entry_point="wav_player_app", - stack_size=4 * 1024, - fap_icon="wav_10px.png", - fap_category="Media", - fap_icon_assets="images", - fap_author="@DrZlo13 & (ported, fixed by @xMasterX), (improved by @LTVA1)", - fap_version="1.0", - fap_description="Audio player for WAV files, recommended to convert files to unsigned 8-bit PCM stereo, but it may work with others too", -) diff --git a/applications/external/wav_player/wav_10px.png b/applications/external/wav_player/wav_10px.png deleted file mode 100644 index 54ff554a1..000000000 Binary files a/applications/external/wav_player/wav_10px.png and /dev/null differ diff --git a/applications/external/wav_player/wav_parser.c b/applications/external/wav_player/wav_parser.c deleted file mode 100644 index 1f534bacb..000000000 --- a/applications/external/wav_player/wav_parser.c +++ /dev/null @@ -1,88 +0,0 @@ -#include "wav_parser.h" - -#define TAG "WavParser" - -const char* format_text(FormatTag tag) { - switch(tag) { - case FormatTagPCM: - return "PCM"; - case FormatTagIEEE_FLOAT: - return "IEEE FLOAT"; - default: - return "Unknown"; - } -}; - -struct WavParser { - WavHeaderChunk header; - WavFormatChunk format; - WavDataChunk data; - size_t wav_data_start; - size_t wav_data_end; -}; - -WavParser* wav_parser_alloc() { - return malloc(sizeof(WavParser)); -} - -void wav_parser_free(WavParser* parser) { - free(parser); -} - -bool wav_parser_parse(WavParser* parser, Stream* stream, WavPlayerApp* app) { - stream_read(stream, (uint8_t*)&parser->header, sizeof(WavHeaderChunk)); - stream_read(stream, (uint8_t*)&parser->format, sizeof(WavFormatChunk)); - stream_read(stream, (uint8_t*)&parser->data, sizeof(WavDataChunk)); - - if(memcmp(parser->header.riff, "RIFF", 4) != 0 || - memcmp(parser->header.wave, "WAVE", 4) != 0) { - FURI_LOG_E(TAG, "WAV: wrong header"); - return false; - } - - if(memcmp(parser->format.fmt, "fmt ", 4) != 0) { - FURI_LOG_E(TAG, "WAV: wrong format"); - return false; - } - - if(parser->format.tag != FormatTagPCM || memcmp(parser->data.data, "data", 4) != 0) { - FURI_LOG_E( - TAG, - "WAV: non-PCM format %u, next '%lu'", - parser->format.tag, - (uint32_t)parser->data.data); - return false; - } - - FURI_LOG_I( - TAG, - "Format tag: %s, ch: %u, smplrate: %lu, bps: %lu, bits: %u", - format_text(parser->format.tag), - parser->format.channels, - parser->format.sample_rate, - parser->format.byte_per_sec, - parser->format.bits_per_sample); - - app->sample_rate = parser->format.sample_rate; - app->num_channels = parser->format.channels; - app->bits_per_sample = parser->format.bits_per_sample; - - parser->wav_data_start = stream_tell(stream); - parser->wav_data_end = parser->wav_data_start + parser->data.size; - - FURI_LOG_I(TAG, "data: %u - %u", parser->wav_data_start, parser->wav_data_end); - - return true; -} - -size_t wav_parser_get_data_start(WavParser* parser) { - return parser->wav_data_start; -} - -size_t wav_parser_get_data_end(WavParser* parser) { - return parser->wav_data_end; -} - -size_t wav_parser_get_data_len(WavParser* parser) { - return parser->wav_data_end - parser->wav_data_start; -} diff --git a/applications/external/wav_player/wav_parser.h b/applications/external/wav_player/wav_parser.h deleted file mode 100644 index b442406f9..000000000 --- a/applications/external/wav_player/wav_parser.h +++ /dev/null @@ -1,89 +0,0 @@ -#pragma once -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wav_player_view.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - FormatTagPCM = 0x0001, - FormatTagIEEE_FLOAT = 0x0003, -} FormatTag; - -typedef struct { - uint8_t riff[4]; - uint32_t size; - uint8_t wave[4]; -} WavHeaderChunk; - -typedef struct { - uint8_t fmt[4]; - uint32_t size; - uint16_t tag; - uint16_t channels; - uint32_t sample_rate; - uint32_t byte_per_sec; - uint16_t block_align; - uint16_t bits_per_sample; -} WavFormatChunk; - -typedef struct { - uint8_t data[4]; - uint32_t size; -} WavDataChunk; - -typedef struct WavParser WavParser; - -typedef struct { - Storage* storage; - Stream* stream; - WavParser* parser; - uint16_t* sample_buffer; - uint8_t* tmp_buffer; - - uint32_t sample_rate; - - uint16_t num_channels; - uint16_t bits_per_sample; - - size_t samples_count_half; - size_t samples_count; - - FuriMessageQueue* queue; - - float volume; - bool play; - - WavPlayerView* view; - ViewDispatcher* view_dispatcher; - Gui* gui; - NotificationApp* notification; -} WavPlayerApp; - -WavParser* wav_parser_alloc(); - -void wav_parser_free(WavParser* parser); - -bool wav_parser_parse(WavParser* parser, Stream* stream, WavPlayerApp* app); - -size_t wav_parser_get_data_start(WavParser* parser); - -size_t wav_parser_get_data_end(WavParser* parser); - -size_t wav_parser_get_data_len(WavParser* parser); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/applications/external/wav_player/wav_player.c b/applications/external/wav_player/wav_player.c deleted file mode 100644 index 79462caf9..000000000 --- a/applications/external/wav_player/wav_player.c +++ /dev/null @@ -1,463 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "wav_player_hal.h" -#include "wav_parser.h" -#include "wav_player_view.h" -#include - -#include "wav_player_icons.h" -#include - -#define TAG "WavPlayer" - -#define WAVPLAYER_FOLDER EXT_PATH("wav_player") - -static bool open_wav_stream(Stream* stream) { - DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); - bool result = false; - FuriString* path; - path = furi_string_alloc(); - furi_string_set(path, WAVPLAYER_FOLDER); - - DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options(&browser_options, ".wav", &I_music_10px); - browser_options.base_path = WAVPLAYER_FOLDER; - browser_options.hide_ext = false; - - bool ret = dialog_file_browser_show(dialogs, path, path, &browser_options); - - furi_record_close(RECORD_DIALOGS); - if(ret) { - if(!file_stream_open(stream, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { - FURI_LOG_E(TAG, "Cannot open file \"%s\"", furi_string_get_cstr(path)); - } else { - result = true; - } - } - furi_string_free(path); - return result; -} - -typedef enum { - WavPlayerEventHalfTransfer, - WavPlayerEventFullTransfer, - WavPlayerEventCtrlVolUp, - WavPlayerEventCtrlVolDn, - WavPlayerEventCtrlMoveL, - WavPlayerEventCtrlMoveR, - WavPlayerEventCtrlOk, - WavPlayerEventCtrlBack, -} WavPlayerEventType; - -typedef struct { - WavPlayerEventType type; -} WavPlayerEvent; - -static void wav_player_dma_isr(void* ctx) { - FuriMessageQueue* event_queue = ctx; - - // half of transfer - if(LL_DMA_IsActiveFlag_HT1(DMA1)) { - LL_DMA_ClearFlag_HT1(DMA1); - // fill first half of buffer - WavPlayerEvent event = {.type = WavPlayerEventHalfTransfer}; - furi_message_queue_put(event_queue, &event, 0); - } - - // transfer complete - if(LL_DMA_IsActiveFlag_TC1(DMA1)) { - LL_DMA_ClearFlag_TC1(DMA1); - // fill second half of buffer - WavPlayerEvent event = {.type = WavPlayerEventFullTransfer}; - furi_message_queue_put(event_queue, &event, 0); - } -} - -static WavPlayerApp* app_alloc() { - WavPlayerApp* app = malloc(sizeof(WavPlayerApp)); - app->samples_count_half = 1024 * 4; - app->samples_count = app->samples_count_half * 2; - app->storage = furi_record_open(RECORD_STORAGE); - app->stream = file_stream_alloc(app->storage); - app->parser = wav_parser_alloc(); - app->sample_buffer = malloc(sizeof(uint16_t) * app->samples_count); - app->tmp_buffer = malloc(sizeof(uint8_t) * app->samples_count); - app->queue = furi_message_queue_alloc(10, sizeof(WavPlayerEvent)); - - app->volume = 10.0f; - app->play = true; - - app->gui = furi_record_open(RECORD_GUI); - app->view_dispatcher = view_dispatcher_alloc(); - app->view = wav_player_view_alloc(); - - view_dispatcher_add_view(app->view_dispatcher, 0, wav_player_view_get_view(app->view)); - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - view_dispatcher_switch_to_view(app->view_dispatcher, 0); - - app->notification = furi_record_open(RECORD_NOTIFICATION); - notification_message(app->notification, &sequence_display_backlight_enforce_on); - - return app; -} - -static void app_free(WavPlayerApp* app) { - view_dispatcher_remove_view(app->view_dispatcher, 0); - view_dispatcher_free(app->view_dispatcher); - wav_player_view_free(app->view); - furi_record_close(RECORD_GUI); - - furi_message_queue_free(app->queue); - free(app->tmp_buffer); - free(app->sample_buffer); - wav_parser_free(app->parser); - stream_free(app->stream); - furi_record_close(RECORD_STORAGE); - - notification_message(app->notification, &sequence_display_backlight_enforce_auto); - furi_record_close(RECORD_NOTIFICATION); - free(app); -} - -// TODO: that works only with 8-bit 2ch audio -static bool fill_data(WavPlayerApp* app, size_t index) { - if(app->num_channels == 1 && app->bits_per_sample == 8) { - uint16_t* sample_buffer_start = &app->sample_buffer[index]; - size_t count = stream_read(app->stream, app->tmp_buffer, app->samples_count_half); - - for(size_t i = count; i < app->samples_count_half; i++) { - app->tmp_buffer[i] = 0; - } - - //for(size_t i = 0; i < app->samples_count; i += 2) - for(size_t i = 0; i < app->samples_count_half; i++) //now works with mono! - { - float data = app->tmp_buffer[i]; - data -= UINT8_MAX / 2; // to signed - data /= UINT8_MAX / 2; // scale -1..1 - - data *= app->volume; // volume - data = tanhf(data); // hyperbolic tangent limiter - - data *= UINT8_MAX / 2; // scale -128..127 - data += UINT8_MAX / 2; // to unsigned - - if(data < 0) { - data = 0; - } - - if(data > 255) { - data = 255; - } - - //uint8_t data = app->tmp_buffer[i]; - - sample_buffer_start[i] = data; - } - - wav_player_view_set_data(app->view, sample_buffer_start, app->samples_count_half); - - return count != app->samples_count_half; - } - - if(app->num_channels == 1 && app->bits_per_sample == 16) { - uint16_t* sample_buffer_start = &app->sample_buffer[index]; - size_t count = stream_read(app->stream, app->tmp_buffer, app->samples_count); - - for(size_t i = count; i < app->samples_count; i++) { - //app->tmp_buffer[i] = 0; - } - - for(size_t i = 0; i < app->samples_count; i += 2) { - int16_t int_16 = - (((int16_t)app->tmp_buffer[i + 1] << 8) + (int16_t)app->tmp_buffer[i]); - - float data = ((float)int_16 / 256.0 + 127.0); - data -= UINT8_MAX / 2; // to signed - data /= UINT8_MAX / 2; // scale -1..1 - - data *= app->volume; // volume - data = tanhf(data); // hyperbolic tangent limiter - - data *= UINT8_MAX / 2; // scale -128..127 - data += UINT8_MAX / 2; // to unsigned - - if(data < 0) { - data = 0; - } - - if(data > 255) { - data = 255; - } - - sample_buffer_start[i / 2] = data; - } - - wav_player_view_set_data(app->view, sample_buffer_start, app->samples_count_half); - - return count != app->samples_count; - } - - if(app->num_channels == 2 && app->bits_per_sample == 16) { - uint16_t* sample_buffer_start = &app->sample_buffer[index]; - size_t count = stream_read(app->stream, app->tmp_buffer, app->samples_count); - - for(size_t i = 0; i < app->samples_count; i += 4) { - int16_t L = (((int16_t)app->tmp_buffer[i + 1] << 8) + (int16_t)app->tmp_buffer[i]); - int16_t R = (((int16_t)app->tmp_buffer[i + 3] << 8) + (int16_t)app->tmp_buffer[i + 2]); - int32_t int_16 = L / 2 + R / 2; // (L + R) / 2 - - float data = ((float)int_16 / 256.0 + 127.0); - data -= UINT8_MAX / 2; // to signed - data /= UINT8_MAX / 2; // scale -1..1 - - data *= app->volume; // volume - data = tanhf(data); // hyperbolic tangent limiter - - data *= UINT8_MAX / 2; // scale -128..127 - data += UINT8_MAX / 2; // to unsigned - - if(data < 0) { - data = 0; - } - - if(data > 255) { - data = 255; - } - - sample_buffer_start[i / 4] = data; - } - - count = stream_read(app->stream, app->tmp_buffer, app->samples_count); - - for(size_t i = 0; i < app->samples_count; i += 4) { - int16_t L = (((int16_t)app->tmp_buffer[i + 1] << 8) + (int16_t)app->tmp_buffer[i]); - int16_t R = (((int16_t)app->tmp_buffer[i + 3] << 8) + (int16_t)app->tmp_buffer[i + 2]); - int32_t int_16 = L / 2 + R / 2; // (L + R) / 2 - - float data = ((float)int_16 / 256.0 + 127.0); - data -= UINT8_MAX / 2; // to signed - data /= UINT8_MAX / 2; // scale -1..1 - - data *= app->volume; // volume - data = tanhf(data); // hyperbolic tangent limiter - - data *= UINT8_MAX / 2; // scale -128..127 - data += UINT8_MAX / 2; // to unsigned - - if(data < 0) { - data = 0; - } - - if(data > 255) { - data = 255; - } - - sample_buffer_start[i / 4 + app->samples_count / 4] = data; - } - - wav_player_view_set_data(app->view, sample_buffer_start, app->samples_count_half); - - return count != app->samples_count; - } - - if(app->num_channels == 2 && app->bits_per_sample == 8) { - uint16_t* sample_buffer_start = &app->sample_buffer[index]; - size_t count = stream_read(app->stream, app->tmp_buffer, app->samples_count); - - for(size_t i = count; i < app->samples_count; i++) { - app->tmp_buffer[i] = 0; - } - - for(size_t i = 0; i < app->samples_count; i += 2) { - float data = (app->tmp_buffer[i] + app->tmp_buffer[i + 1]) / 2; // (L + R) / 2 - data -= UINT8_MAX / 2; // to signed - data /= UINT8_MAX / 2; // scale -1..1 - - data *= app->volume; // volume - data = tanhf(data); // hyperbolic tangent limiter - - data *= UINT8_MAX / 2; // scale -128..127 - data += UINT8_MAX / 2; // to unsigned - - if(data < 0) { - data = 0; - } - - if(data > 255) { - data = 255; - } - - //uint8_t data = app->tmp_buffer[i]; - - sample_buffer_start[i / 2] = data; - } - - wav_player_view_set_data(app->view, sample_buffer_start, app->samples_count_half); - - return count != app->samples_count; - } - - return true; -} - -static void ctrl_callback(WavPlayerCtrl ctrl, void* ctx) { - FuriMessageQueue* event_queue = ctx; - WavPlayerEvent event; - - switch(ctrl) { - case WavPlayerCtrlVolUp: - event.type = WavPlayerEventCtrlVolUp; - furi_message_queue_put(event_queue, &event, 0); - break; - case WavPlayerCtrlVolDn: - event.type = WavPlayerEventCtrlVolDn; - furi_message_queue_put(event_queue, &event, 0); - break; - case WavPlayerCtrlMoveL: - event.type = WavPlayerEventCtrlMoveL; - furi_message_queue_put(event_queue, &event, 0); - break; - case WavPlayerCtrlMoveR: - event.type = WavPlayerEventCtrlMoveR; - furi_message_queue_put(event_queue, &event, 0); - break; - case WavPlayerCtrlOk: - event.type = WavPlayerEventCtrlOk; - furi_message_queue_put(event_queue, &event, 0); - break; - case WavPlayerCtrlBack: - event.type = WavPlayerEventCtrlBack; - furi_message_queue_put(event_queue, &event, 0); - break; - default: - break; - } -} - -static void app_run(WavPlayerApp* app) { - if(!open_wav_stream(app->stream)) return; - if(!wav_parser_parse(app->parser, app->stream, app)) return; - - wav_player_view_set_volume(app->view, app->volume); - wav_player_view_set_start(app->view, wav_parser_get_data_start(app->parser)); - wav_player_view_set_current(app->view, stream_tell(app->stream)); - wav_player_view_set_end(app->view, wav_parser_get_data_end(app->parser)); - wav_player_view_set_play(app->view, app->play); - - wav_player_view_set_context(app->view, app->queue); - wav_player_view_set_ctrl_callback(app->view, ctrl_callback); - - bool eof = fill_data(app, 0); - eof = fill_data(app, app->samples_count_half); - - if(furi_hal_speaker_acquire(1000)) { - wav_player_speaker_init(app->sample_rate); - wav_player_dma_init((uint32_t)app->sample_buffer, app->samples_count); - - furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, wav_player_dma_isr, app->queue); - - wav_player_dma_start(); - wav_player_speaker_start(); - - WavPlayerEvent event; - - while(1) { - if(furi_message_queue_get(app->queue, &event, FuriWaitForever) == FuriStatusOk) { - if(event.type == WavPlayerEventHalfTransfer) { - wav_player_view_set_chans(app->view, app->num_channels); - wav_player_view_set_bits(app->view, app->bits_per_sample); - - eof = fill_data(app, 0); - wav_player_view_set_current(app->view, stream_tell(app->stream)); - if(eof) { - stream_seek( - app->stream, - wav_parser_get_data_start(app->parser), - StreamOffsetFromStart); - } - - } else if(event.type == WavPlayerEventFullTransfer) { - wav_player_view_set_chans(app->view, app->num_channels); - wav_player_view_set_bits(app->view, app->bits_per_sample); - - eof = fill_data(app, app->samples_count_half); - wav_player_view_set_current(app->view, stream_tell(app->stream)); - if(eof) { - stream_seek( - app->stream, - wav_parser_get_data_start(app->parser), - StreamOffsetFromStart); - } - } else if(event.type == WavPlayerEventCtrlVolUp) { - if(app->volume < 9.9) app->volume += 0.4; - wav_player_view_set_volume(app->view, app->volume); - } else if(event.type == WavPlayerEventCtrlVolDn) { - if(app->volume > 0.01) app->volume -= 0.4; - wav_player_view_set_volume(app->view, app->volume); - } else if(event.type == WavPlayerEventCtrlMoveL) { - int32_t seek = - stream_tell(app->stream) - wav_parser_get_data_start(app->parser); - seek = MIN( - seek, - (int32_t)(wav_parser_get_data_len(app->parser) / (size_t)100) % 2 ? - ((int32_t)(wav_parser_get_data_len(app->parser) / (size_t)100) - 1) : - (int32_t)(wav_parser_get_data_len(app->parser) / (size_t)100)); - stream_seek(app->stream, -seek, StreamOffsetFromCurrent); - wav_player_view_set_current(app->view, stream_tell(app->stream)); - } else if(event.type == WavPlayerEventCtrlMoveR) { - int32_t seek = wav_parser_get_data_end(app->parser) - stream_tell(app->stream); - seek = MIN( - seek, - (int32_t)(wav_parser_get_data_len(app->parser) / (size_t)100) % 2 ? - ((int32_t)(wav_parser_get_data_len(app->parser) / (size_t)100) - 1) : - (int32_t)(wav_parser_get_data_len(app->parser) / (size_t)100)); - stream_seek(app->stream, seek, StreamOffsetFromCurrent); - wav_player_view_set_current(app->view, stream_tell(app->stream)); - } else if(event.type == WavPlayerEventCtrlOk) { - app->play = !app->play; - wav_player_view_set_play(app->view, app->play); - - if(!app->play) { - wav_player_speaker_stop(); - } else { - wav_player_speaker_start(); - } - } else if(event.type == WavPlayerEventCtrlBack) { - break; - } - } - } - - wav_player_speaker_stop(); - wav_player_dma_stop(); - furi_hal_speaker_release(); - } - - // Reset GPIO pin and bus states - wav_player_hal_deinit(); - - furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, NULL, NULL); -} - -int32_t wav_player_app(void* p) { - UNUSED(p); - WavPlayerApp* app = app_alloc(); - - Storage* storage = furi_record_open(RECORD_STORAGE); - if(!storage_simply_mkdir(storage, WAVPLAYER_FOLDER)) { - FURI_LOG_E(TAG, "Could not create folder %s", WAVPLAYER_FOLDER); - } - furi_record_close(RECORD_STORAGE); - - app_run(app); - app_free(app); - return 0; -} diff --git a/applications/external/wav_player/wav_player_hal.c b/applications/external/wav_player/wav_player_hal.c deleted file mode 100644 index cf2688523..000000000 --- a/applications/external/wav_player/wav_player_hal.c +++ /dev/null @@ -1,111 +0,0 @@ -#include "wav_player_hal.h" -#include -#include - -#include -#include -#include -#include - -//#define FURI_HAL_SPEAKER_TIMER TIM16 - -#define FURI_HAL_SPEAKER_TIMER TIM16 - -#define SAMPLE_RATE_TIMER TIM2 - -#define FURI_HAL_SPEAKER_CHANNEL LL_TIM_CHANNEL_CH1 -#define DMA_INSTANCE DMA1, LL_DMA_CHANNEL_1 - -void wav_player_speaker_init(uint32_t sample_rate) { - // Enable bus - furi_hal_bus_enable(FuriHalBusTIM2); - - LL_TIM_InitTypeDef TIM_InitStruct = {0}; - //TIM_InitStruct.Prescaler = 4; - TIM_InitStruct.Prescaler = 1; - TIM_InitStruct.Autoreload = - 255; //in this fork used purely as PWM timer, the DMA now is triggered by SAMPLE_RATE_TIMER - LL_TIM_Init(FURI_HAL_SPEAKER_TIMER, &TIM_InitStruct); - - LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0}; - TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1; - TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE; - TIM_OC_InitStruct.CompareValue = 127; - LL_TIM_OC_Init(FURI_HAL_SPEAKER_TIMER, FURI_HAL_SPEAKER_CHANNEL, &TIM_OC_InitStruct); - - //====================================================== - - TIM_InitStruct.Prescaler = 0; - //TIM_InitStruct.Autoreload = 1451; //64 000 000 / 1451 ~= 44100 Hz - - TIM_InitStruct.Autoreload = 64000000 / sample_rate - 1; //to support various sample rates - - LL_TIM_Init(SAMPLE_RATE_TIMER, &TIM_InitStruct); - - //LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0}; - TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1; - TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE; - TIM_OC_InitStruct.CompareValue = 127; - LL_TIM_OC_Init(SAMPLE_RATE_TIMER, FURI_HAL_SPEAKER_CHANNEL, &TIM_OC_InitStruct); - - //========================================================= - //configuring PA6 pin as TIM16 output - - furi_hal_gpio_init_ex( - &gpio_ext_pa6, - GpioModeAltFunctionPushPull, - GpioPullNo, - GpioSpeedVeryHigh, - GpioAltFn14TIM16); -} - -void wav_player_hal_deinit() { - furi_hal_gpio_init(&gpio_ext_pa6, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - - // Disable bus - furi_hal_bus_disable(FuriHalBusTIM2); -} - -void wav_player_speaker_start() { - LL_TIM_EnableAllOutputs(FURI_HAL_SPEAKER_TIMER); - LL_TIM_EnableCounter(FURI_HAL_SPEAKER_TIMER); - - LL_TIM_EnableAllOutputs(SAMPLE_RATE_TIMER); - LL_TIM_EnableCounter(SAMPLE_RATE_TIMER); -} - -void wav_player_speaker_stop() { - LL_TIM_DisableAllOutputs(FURI_HAL_SPEAKER_TIMER); - LL_TIM_DisableCounter(FURI_HAL_SPEAKER_TIMER); - - LL_TIM_DisableAllOutputs(SAMPLE_RATE_TIMER); - LL_TIM_DisableCounter(SAMPLE_RATE_TIMER); -} - -void wav_player_dma_init(uint32_t address, size_t size) { - uint32_t dma_dst = (uint32_t) & (FURI_HAL_SPEAKER_TIMER->CCR1); - - LL_DMA_ConfigAddresses(DMA_INSTANCE, address, dma_dst, LL_DMA_DIRECTION_MEMORY_TO_PERIPH); - LL_DMA_SetDataLength(DMA_INSTANCE, size); - - LL_DMA_SetPeriphRequest(DMA_INSTANCE, LL_DMAMUX_REQ_TIM2_UP); - LL_DMA_SetDataTransferDirection(DMA_INSTANCE, LL_DMA_DIRECTION_MEMORY_TO_PERIPH); - LL_DMA_SetChannelPriorityLevel(DMA_INSTANCE, LL_DMA_PRIORITY_VERYHIGH); - LL_DMA_SetMode(DMA_INSTANCE, LL_DMA_MODE_CIRCULAR); - LL_DMA_SetPeriphIncMode(DMA_INSTANCE, LL_DMA_PERIPH_NOINCREMENT); - LL_DMA_SetMemoryIncMode(DMA_INSTANCE, LL_DMA_MEMORY_INCREMENT); - LL_DMA_SetPeriphSize(DMA_INSTANCE, LL_DMA_PDATAALIGN_HALFWORD); - LL_DMA_SetMemorySize(DMA_INSTANCE, LL_DMA_MDATAALIGN_HALFWORD); - - LL_DMA_EnableIT_TC(DMA_INSTANCE); - LL_DMA_EnableIT_HT(DMA_INSTANCE); -} - -void wav_player_dma_start() { - LL_DMA_EnableChannel(DMA_INSTANCE); - LL_TIM_EnableDMAReq_UPDATE(SAMPLE_RATE_TIMER); -} - -void wav_player_dma_stop() { - LL_DMA_DisableChannel(DMA_INSTANCE); -} \ No newline at end of file diff --git a/applications/external/wav_player/wav_player_hal.h b/applications/external/wav_player/wav_player_hal.h deleted file mode 100644 index bddfc3fed..000000000 --- a/applications/external/wav_player/wav_player_hal.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -void wav_player_speaker_init(); - -void wav_player_speaker_start(); - -void wav_player_speaker_stop(); - -void wav_player_dma_init(uint32_t address, size_t size); - -void wav_player_dma_start(); - -void wav_player_dma_stop(); - -void wav_player_hal_deinit(); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/applications/external/wav_player/wav_player_view.c b/applications/external/wav_player/wav_player_view.c deleted file mode 100644 index 285b3dd33..000000000 --- a/applications/external/wav_player/wav_player_view.c +++ /dev/null @@ -1,202 +0,0 @@ -#include "wav_player_view.h" - -float map(float x, float in_min, float in_max, float out_min, float out_max) { - return (x - in_min) * (out_max - out_min + 1) / (in_max - in_min + 1) + out_min; -} - -static void wav_player_view_draw_callback(Canvas* canvas, void* _model) { - WavPlayerViewModel* model = _model; - - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - uint8_t x_pos = 0; - uint8_t y_pos = 0; - - /*char buffer[20]; - snprintf(buffer, sizeof(buffer), "%d", model->num_channels); - canvas_draw_str(canvas, 0, 10, buffer); - snprintf(buffer, sizeof(buffer), "%d", model->bits_per_sample); - canvas_draw_str(canvas, 0, 20, buffer);*/ - - // volume - x_pos = 123; - y_pos = 0; - const float volume = (64 / 10.0f) * model->volume; - canvas_draw_frame(canvas, x_pos, y_pos, 4, 64); - canvas_draw_box(canvas, x_pos, y_pos + (64 - volume), 4, volume); - - // play / pause - x_pos = 58; - y_pos = 55; - if(!model->play) { - canvas_draw_line(canvas, x_pos, y_pos, x_pos + 8, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos + 8, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos, y_pos); - } else { - canvas_draw_box(canvas, x_pos, y_pos, 3, 9); - canvas_draw_box(canvas, x_pos + 4, y_pos, 3, 9); - } - - x_pos = 78; - y_pos = 55; - canvas_draw_line(canvas, x_pos, y_pos, x_pos + 4, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos + 4, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos, y_pos); - - x_pos = 82; - y_pos = 55; - canvas_draw_line(canvas, x_pos, y_pos, x_pos + 4, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos + 4, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos, y_pos); - - x_pos = 40; - y_pos = 55; - canvas_draw_line(canvas, x_pos, y_pos, x_pos - 4, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos - 4, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos, y_pos); - - x_pos = 44; - y_pos = 55; - canvas_draw_line(canvas, x_pos, y_pos, x_pos - 4, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos - 4, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos, y_pos); - - // len - x_pos = 4; - y_pos = 47; - const uint8_t play_len = 116; - uint8_t play_pos = map(model->current, model->start, model->end, 0, play_len - 4); - - canvas_draw_frame(canvas, x_pos, y_pos, play_len, 4); - canvas_draw_box(canvas, x_pos + play_pos, y_pos - 2, 4, 8); - canvas_draw_box(canvas, x_pos, y_pos, play_pos, 4); - - // osc - x_pos = 4; - y_pos = 0; - for(size_t i = 1; i < DATA_COUNT; i++) { - canvas_draw_line(canvas, x_pos + i - 1, model->data[i - 1], x_pos + i, model->data[i]); - } -} - -static bool wav_player_view_input_callback(InputEvent* event, void* context) { - WavPlayerView* wav_player_view = context; - bool consumed = false; - - if(wav_player_view->callback) { - if(event->type == InputTypeShort || event->type == InputTypeRepeat) { - if(event->key == InputKeyUp) { - wav_player_view->callback(WavPlayerCtrlVolUp, wav_player_view->context); - consumed = true; - } else if(event->key == InputKeyDown) { - wav_player_view->callback(WavPlayerCtrlVolDn, wav_player_view->context); - consumed = true; - } else if(event->key == InputKeyLeft) { - wav_player_view->callback(WavPlayerCtrlMoveL, wav_player_view->context); - consumed = true; - } else if(event->key == InputKeyRight) { - wav_player_view->callback(WavPlayerCtrlMoveR, wav_player_view->context); - consumed = true; - } else if(event->key == InputKeyOk) { - wav_player_view->callback(WavPlayerCtrlOk, wav_player_view->context); - consumed = true; - } else if(event->key == InputKeyBack) { - wav_player_view->callback(WavPlayerCtrlBack, wav_player_view->context); - consumed = true; - } - } - } - - return consumed; -} - -WavPlayerView* wav_player_view_alloc() { - WavPlayerView* wav_view = malloc(sizeof(WavPlayerView)); - wav_view->view = view_alloc(); - view_set_context(wav_view->view, wav_view); - view_allocate_model(wav_view->view, ViewModelTypeLocking, sizeof(WavPlayerViewModel)); - view_set_draw_callback(wav_view->view, wav_player_view_draw_callback); - view_set_input_callback(wav_view->view, wav_player_view_input_callback); - - return wav_view; -} - -void wav_player_view_free(WavPlayerView* wav_view) { - furi_assert(wav_view); - view_free(wav_view->view); - free(wav_view); -} - -View* wav_player_view_get_view(WavPlayerView* wav_view) { - furi_assert(wav_view); - return wav_view->view; -} - -void wav_player_view_set_volume(WavPlayerView* wav_view, float volume) { - furi_assert(wav_view); - with_view_model( - wav_view->view, WavPlayerViewModel * model, { model->volume = volume; }, true); -} - -void wav_player_view_set_start(WavPlayerView* wav_view, size_t start) { - furi_assert(wav_view); - with_view_model( - wav_view->view, WavPlayerViewModel * model, { model->start = start; }, true); -} - -void wav_player_view_set_end(WavPlayerView* wav_view, size_t end) { - furi_assert(wav_view); - with_view_model( - wav_view->view, WavPlayerViewModel * model, { model->end = end; }, true); -} - -void wav_player_view_set_current(WavPlayerView* wav_view, size_t current) { - furi_assert(wav_view); - with_view_model( - wav_view->view, WavPlayerViewModel * model, { model->current = current; }, true); -} - -void wav_player_view_set_play(WavPlayerView* wav_view, bool play) { - furi_assert(wav_view); - with_view_model( - wav_view->view, WavPlayerViewModel * model, { model->play = play; }, true); -} - -void wav_player_view_set_chans(WavPlayerView* wav_view, uint16_t chn) { - furi_assert(wav_view); - with_view_model( - wav_view->view, WavPlayerViewModel * model, { model->num_channels = chn; }, true); -} - -void wav_player_view_set_bits(WavPlayerView* wav_view, uint16_t bit) { - furi_assert(wav_view); - with_view_model( - wav_view->view, WavPlayerViewModel * model, { model->bits_per_sample = bit; }, true); -} - -void wav_player_view_set_data(WavPlayerView* wav_view, uint16_t* data, size_t data_count) { - furi_assert(wav_view); - with_view_model( - wav_view->view, - WavPlayerViewModel * model, - { - size_t inc = (data_count / DATA_COUNT) - 1; - - for(size_t i = 0; i < DATA_COUNT; i++) { - model->data[i] = *data / 6; - if(model->data[i] > 42) model->data[i] = 42; - data += inc; - } - }, - true); -} - -void wav_player_view_set_ctrl_callback(WavPlayerView* wav_view, WavPlayerCtrlCallback callback) { - furi_assert(wav_view); - wav_view->callback = callback; -} - -void wav_player_view_set_context(WavPlayerView* wav_view, void* context) { - furi_assert(wav_view); - wav_view->context = context; -} \ No newline at end of file diff --git a/applications/external/wav_player/wav_player_view.h b/applications/external/wav_player/wav_player_view.h deleted file mode 100644 index b7b0ef908..000000000 --- a/applications/external/wav_player/wav_player_view.h +++ /dev/null @@ -1,78 +0,0 @@ -#pragma once -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct WavPlayerView WavPlayerView; - -typedef enum { - WavPlayerCtrlVolUp, - WavPlayerCtrlVolDn, - WavPlayerCtrlMoveL, - WavPlayerCtrlMoveR, - WavPlayerCtrlOk, - WavPlayerCtrlBack, -} WavPlayerCtrl; - -typedef void (*WavPlayerCtrlCallback)(WavPlayerCtrl ctrl, void* context); - -#define DATA_COUNT 116 - -struct WavPlayerView { - View* view; - WavPlayerCtrlCallback callback; - void* context; -}; - -typedef struct { - bool play; - float volume; - size_t start; - size_t end; - size_t current; - uint8_t data[DATA_COUNT]; - - uint16_t bits_per_sample; - uint16_t num_channels; -} WavPlayerViewModel; - -WavPlayerView* wav_player_view_alloc(); - -void wav_player_view_free(WavPlayerView* wav_view); - -View* wav_player_view_get_view(WavPlayerView* wav_view); - -void wav_player_view_set_volume(WavPlayerView* wav_view, float volume); - -void wav_player_view_set_start(WavPlayerView* wav_view, size_t start); - -void wav_player_view_set_end(WavPlayerView* wav_view, size_t end); - -void wav_player_view_set_current(WavPlayerView* wav_view, size_t current); - -void wav_player_view_set_play(WavPlayerView* wav_view, bool play); - -void wav_player_view_set_data(WavPlayerView* wav_view, uint16_t* data, size_t data_count); - -void wav_player_view_set_bits(WavPlayerView* wav_view, uint16_t bit); -void wav_player_view_set_chans(WavPlayerView* wav_view, uint16_t chn); - -void wav_player_view_set_ctrl_callback(WavPlayerView* wav_view, WavPlayerCtrlCallback callback); - -void wav_player_view_set_context(WavPlayerView* wav_view, void* context); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/applications/external/wire_tester/LICENSE b/applications/external/wire_tester/LICENSE deleted file mode 100644 index c34fc9f11..000000000 --- a/applications/external/wire_tester/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -BSD 2-Clause License - -Copyright (c) 2023, Blaine Murphy -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/applications/external/wire_tester/application.fam b/applications/external/wire_tester/application.fam deleted file mode 100644 index 6a474dc9c..000000000 --- a/applications/external/wire_tester/application.fam +++ /dev/null @@ -1,15 +0,0 @@ -App( - appid="wire_tester", - name="[GPIO] Wire Tester", - apptype=FlipperAppType.EXTERNAL, - entry_point="app_main", - requires=["gui"], - stack_size=1 * 1024, - fap_icon="icon.png", - fap_icon_assets="assets", - fap_category="GPIO", - fap_author="@unixispower", - fap_weburl="https://gitlab.com/unixispower/flipper-wire-tester", - fap_version="1.0", - fap_description="Beeps if a wire is continuous", -) diff --git a/applications/external/wire_tester/assets/background_128x64.png b/applications/external/wire_tester/assets/background_128x64.png deleted file mode 100644 index 224fcd03b..000000000 Binary files a/applications/external/wire_tester/assets/background_128x64.png and /dev/null differ diff --git a/applications/external/wire_tester/icon.png b/applications/external/wire_tester/icon.png deleted file mode 100644 index b2108e94d..000000000 Binary files a/applications/external/wire_tester/icon.png and /dev/null differ diff --git a/applications/external/wire_tester/wire_tester.c b/applications/external/wire_tester/wire_tester.c deleted file mode 100644 index 3eef936a5..000000000 --- a/applications/external/wire_tester/wire_tester.c +++ /dev/null @@ -1,109 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include - -#include "wire_tester_icons.h" -#include - -//#define TAG "wire_tester" - -static const uint32_t EVENT_PERIOD_MS = 10; // check for input changes often -static const float BEEP_FREQ = 2400.0f; // louder than other frequencies -static const float BEEP_VOL = 0.8f; -static const GpioPin* const INPUT_PIN = &gpio_ext_pb2; // pin 6 - -static void start_feedback(NotificationApp* notifications) { - // set LED to green - notification_message_block(notifications, &sequence_set_only_green_255); - - // start beep - if(furi_hal_speaker_acquire(1000)) { - furi_hal_speaker_start(BEEP_FREQ, BEEP_VOL); - } -} - -static void stop_feedback(NotificationApp* notifications) { - // clear LED - notification_message_block(notifications, &sequence_reset_rgb); - - // stop beep - if(furi_hal_speaker_is_mine()) { - furi_hal_speaker_stop(); - furi_hal_speaker_release(); - } -} - -static void draw_callback(Canvas* canvas, void* ctx) { - furi_assert(ctx); - canvas_clear(canvas); - canvas_draw_icon(canvas, 0, 0, &I_background_128x64); -} - -static void input_callback(InputEvent* input_event, void* ctx) { - furi_assert(ctx); - FuriMessageQueue* event_queue = ctx; - furi_message_queue_put(event_queue, input_event, FuriWaitForever); -} - -int32_t app_main(void* p) { - UNUSED(p); - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); - - // force backlight on because our hands will be busy with wires - NotificationApp* notifications = furi_record_open(RECORD_NOTIFICATION); - notification_message_block(notifications, &sequence_display_backlight_enforce_on); - - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, draw_callback, view_port); - view_port_input_callback_set(view_port, input_callback, event_queue); - - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - view_port_update(view_port); - - stop_feedback(notifications); - - // set input to be normally high; it will be low when shorted to ground - furi_hal_gpio_init(INPUT_PIN, GpioModeInput, GpioPullUp, GpioSpeedLow); - - bool alarming = false; - bool running = true; - while(running) { - // start and stop feedback on the transition - bool continuous = !furi_hal_gpio_read(INPUT_PIN); - if(continuous && !alarming) { - start_feedback(notifications); - } else if(!continuous && alarming) { - stop_feedback(notifications); - } - alarming = continuous; - - // exit on back key - InputEvent event; - if(furi_message_queue_get(event_queue, &event, EVENT_PERIOD_MS) == FuriStatusOk) { - if((event.type == InputTypePress || event.type == InputTypeRepeat) && - event.key == InputKeyBack) { - running = false; - } - } - } - - // return control of the LED, beeper, and backlight - stop_feedback(notifications); - notification_message_block(notifications, &sequence_display_backlight_enforce_auto); - - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - view_port_free(view_port); - - furi_message_queue_free(event_queue); - furi_record_close(RECORD_GUI); - furi_record_close(RECORD_NOTIFICATION); - - return 0; -}