diff --git a/applications/external/4inrow/4inrow.c b/applications/external/4inrow/4inrow.c index 09ae94376..da2d5a4cb 100644 --- a/applications/external/4inrow/4inrow.c +++ b/applications/external/4inrow/4inrow.c @@ -4,6 +4,7 @@ #include #include #include +#include static int matrix[6][7] = {0}; static int cursorx = 3; @@ -234,6 +235,8 @@ int32_t four_in_row_app(void* p) { return 255; } + dolphin_deed(DolphinDeedPluginGameStart); + // Создаем новый view port ViewPort* view_port = view_port_alloc(); // Создаем callback отрисовки, без контекста diff --git a/applications/external/4inrow/application.fam b/applications/external/4inrow/application.fam index 9d0db09ca..67a133992 100644 --- a/applications/external/4inrow/application.fam +++ b/applications/external/4inrow/application.fam @@ -7,7 +7,6 @@ App( "gui", ], stack_size=1 * 1024, - order=90, fap_icon="4inrow_10px.png", fap_category="Games", fap_author="leo-need-more-coffee", diff --git a/applications/external/airmouse/application.fam b/applications/external/airmouse/application.fam index dfb88da1e..b5498b8ce 100644 --- a/applications/external/airmouse/application.fam +++ b/applications/external/airmouse/application.fam @@ -6,6 +6,6 @@ App( stack_size=10 * 1024, fap_category="GPIO", fap_icon="mouse_10px.png", - fap_version="0.6", + fap_version="0.8", sources=["*.c", "*.cc"], ) diff --git a/applications/external/airmouse/tracking/main_loop.cc b/applications/external/airmouse/tracking/main_loop.cc index 2caffb717..a9aca0aab 100644 --- a/applications/external/airmouse/tracking/main_loop.cc +++ b/applications/external/airmouse/tracking/main_loop.cc @@ -12,178 +12,219 @@ static const float CURSOR_SPEED = 1024.0 / (M_PI / 4); static const float STABILIZE_BIAS = 16.0; -float g_yaw = 0; -float g_pitch = 0; -float g_dYaw = 0; -float g_dPitch = 0; -bool firstRead = true; -bool stabilize = true; -CalibrationData calibration; -cardboard::OrientationTracker tracker(10000000l); // 10 ms / 100 Hz -uint64_t ippms, ippms2; +class TrackingState { +private: + float yaw; + float pitch; + float dYaw; + float dPitch; + bool firstRead; + bool stabilize; + CalibrationData calibration; + cardboard::OrientationTracker tracker; + uint64_t ippus, ippus2; -static inline float clamp(float val) -{ - while (val <= -M_PI) { - val += 2 * M_PI; - } - while (val >= M_PI) { - val -= 2 * M_PI; - } - return val; -} - -static inline float highpass(float oldVal, float newVal) -{ - if (!stabilize) { - return newVal; - } - float delta = clamp(oldVal - newVal); - float alpha = (float) std::max(0.0, 1 - std::pow(std::fabs(delta) * CURSOR_SPEED / STABILIZE_BIAS, 3.0)); - return newVal + alpha * delta; -} - -void sendCurrentState(MouseMoveCallback mouse_move, void *context) -{ - float dX = g_dYaw * CURSOR_SPEED; - float dY = g_dPitch * CURSOR_SPEED; - - // Scale the shift down to fit the protocol. - if (dX > 127) { - dY *= 127.0 / dX; - dX = 127; - } - if (dX < -127) { - dY *= -127.0 / dX; - dX = -127; - } - if (dY > 127) { - dX *= 127.0 / dY; - dY = 127; - } - if (dY < -127) { - dX *= -127.0 / dY; - dY = -127; +private: + float clamp(float val) { + while (val <= -M_PI) { + val += 2 * M_PI; + } + while (val >= M_PI) { + val -= 2 * M_PI; + } + return val; } - const int8_t x = (int8_t)std::floor(dX + 0.5); - const int8_t y = (int8_t)std::floor(dY + 0.5); - - mouse_move(x, y, context); - - // Only subtract the part of the error that was already sent. - if (x != 0) { - g_dYaw -= x / CURSOR_SPEED; - } - if (y != 0) { - g_dPitch -= y / CURSOR_SPEED; - } -} - -void onOrientation(cardboard::Vector4& quaternion) -{ - float q1 = quaternion[0]; // X * sin(T/2) - float q2 = quaternion[1]; // Y * sin(T/2) - float q3 = quaternion[2]; // Z * sin(T/2) - float q0 = quaternion[3]; // cos(T/2) - - float yaw = std::atan2(2 * (q0 * q3 - q1 * q2), (1 - 2 * (q1 * q1 + q3 * q3))); - float pitch = std::asin(2 * (q0 * q1 + q2 * q3)); - // float roll = std::atan2(2 * (q0 * q2 - q1 * q3), (1 - 2 * (q1 * q1 + q2 * q2))); - - if (yaw == NAN || pitch == NAN) { - // NaN case, skip it - return; + float highpass(float oldVal, float newVal) { + if (!stabilize) { + return newVal; + } + float delta = clamp(oldVal - newVal); + float alpha = (float) std::max(0.0, 1 - std::pow(std::fabs(delta) * CURSOR_SPEED / STABILIZE_BIAS, 3.0)); + return newVal + alpha * delta; } - if (firstRead) { - g_yaw = yaw; - g_pitch = pitch; - firstRead = false; - } else { - const float newYaw = highpass(g_yaw, yaw); - const float newPitch = highpass(g_pitch, pitch); + void sendCurrentState(MouseMoveCallback mouse_move, void *context) { + float dX = dYaw * CURSOR_SPEED; + float dY = dPitch * CURSOR_SPEED; - float dYaw = clamp(g_yaw - newYaw); - float dPitch = g_pitch - newPitch; - g_yaw = newYaw; - g_pitch = newPitch; + // Scale the shift down to fit the protocol. + if (dX > 127) { + dY *= 127.0 / dX; + dX = 127; + } + if (dX < -127) { + dY *= -127.0 / dX; + dX = -127; + } + if (dY > 127) { + dX *= 127.0 / dY; + dY = 127; + } + if (dY < -127) { + dX *= -127.0 / dY; + dY = -127; + } - // Accumulate the error locally. - g_dYaw += dYaw; - g_dPitch += dPitch; + const int8_t x = (int8_t)std::floor(dX + 0.5); + const int8_t y = (int8_t)std::floor(dY + 0.5); + + mouse_move(x, y, context); + + // Only subtract the part of the error that was already sent. + if (x != 0) { + dYaw -= x / CURSOR_SPEED; + } + if (y != 0) { + dPitch -= y / CURSOR_SPEED; + } } -} + + void onOrientation(cardboard::Vector4& quaternion) { + float q1 = quaternion[0]; // X * sin(T/2) + float q2 = quaternion[1]; // Y * sin(T/2) + float q3 = quaternion[2]; // Z * sin(T/2) + float q0 = quaternion[3]; // cos(T/2) + + float yaw = std::atan2(2 * (q0 * q3 - q1 * q2), (1 - 2 * (q1 * q1 + q3 * q3))); + float pitch = std::asin(2 * (q0 * q1 + q2 * q3)); + // float roll = std::atan2(2 * (q0 * q2 - q1 * q3), (1 - 2 * (q1 * q1 + q2 * q2))); + + if (yaw == NAN || pitch == NAN) { + // NaN case, skip it + return; + } + + if (firstRead) { + this->yaw = yaw; + this->pitch = pitch; + firstRead = false; + } else { + const float newYaw = highpass(this->yaw, yaw); + const float newPitch = highpass(this->pitch, pitch); + + float dYaw = clamp(this->yaw - newYaw); + float dPitch = this->pitch - newPitch; + this->yaw = newYaw; + this->pitch = newPitch; + + // Accumulate the error locally. + this->dYaw += dYaw; + this->dPitch += dPitch; + } + } + +public: + TrackingState() + : yaw(0) + , pitch(0) + , dYaw(0) + , dPitch(0) + , firstRead(true) + , stabilize(true) + , tracker(10000000l) { // 10 ms / 100 Hz + ippus = furi_hal_cortex_instructions_per_microsecond(); + ippus2 = ippus / 2; + } + + void beginCalibration() { + calibration.reset(); + } + + bool stepCalibration() { + if (calibration.isComplete()) + return true; + + double vec[6]; + if (imu_read(vec) & GYR_DATA_READY) { + cardboard::Vector3 data(vec[3], vec[4], vec[5]); + furi_delay_ms(9); // Artificially limit to ~100Hz + return calibration.add(data); + } + + return false; + } + + void saveCalibration() { + CalibrationMedian store; + cardboard::Vector3 median = calibration.getMedian(); + store.x = median[0]; + store.y = median[1]; + store.z = median[2]; + CALIBRATION_DATA_SAVE(&store); + } + + void loadCalibration() { + CalibrationMedian store; + cardboard::Vector3 median = calibration.getMedian(); + if (CALIBRATION_DATA_LOAD(&store)) { + median[0] = store.x; + median[1] = store.y; + median[2] = store.z; + } + + tracker.SetCalibration(median); + } + + void beginTracking() { + loadCalibration(); + tracker.Resume(); + } + + void stepTracking(MouseMoveCallback mouse_move, void *context) { + double vec[6]; + int ret = imu_read(vec); + if (ret != 0) { + uint64_t t = (DWT->CYCCNT * 1000llu + ippus2) / ippus; + if (ret & ACC_DATA_READY) { + cardboard::AccelerometerData adata + = { .system_timestamp = t, .sensor_timestamp_ns = t, + .data = cardboard::Vector3(vec[0], vec[1], vec[2]) }; + tracker.OnAccelerometerData(adata); + } + if (ret & GYR_DATA_READY) { + cardboard::GyroscopeData gdata + = { .system_timestamp = t, .sensor_timestamp_ns = t, + .data = cardboard::Vector3(vec[3], vec[4], vec[5]) }; + cardboard::Vector4 pose = tracker.OnGyroscopeData(gdata); + onOrientation(pose); + sendCurrentState(mouse_move, context); + } + } + } + + void stopTracking() { + tracker.Pause(); + } +}; + +static TrackingState g_state; extern "C" { void calibration_begin() { - calibration.reset(); + g_state.beginCalibration(); FURI_LOG_I(TAG, "Calibrating"); } bool calibration_step() { - if (calibration.isComplete()) - return true; - - double vec[6]; - if (imu_read(vec) & GYR_DATA_READY) { - cardboard::Vector3 data(vec[3], vec[4], vec[5]); - furi_delay_ms(9); // Artificially limit to ~100Hz - return calibration.add(data); - } - - return false; + return g_state.stepCalibration(); } void calibration_end() { - CalibrationMedian store; - cardboard::Vector3 median = calibration.getMedian(); - store.x = median[0]; - store.y = median[1]; - store.z = median[2]; - CALIBRATION_DATA_SAVE(&store); + g_state.saveCalibration(); } void tracking_begin() { - CalibrationMedian store; - cardboard::Vector3 median = calibration.getMedian(); - if (CALIBRATION_DATA_LOAD(&store)) { - median[0] = store.x; - median[1] = store.y; - median[2] = store.z; - } - - ippms = furi_hal_cortex_instructions_per_microsecond(); - ippms2 = ippms / 2; - tracker.SetCalibration(median); - tracker.Resume(); + g_state.beginTracking(); } void tracking_step(MouseMoveCallback mouse_move, void *context) { - double vec[6]; - int ret = imu_read(vec); - if (ret != 0) { - uint64_t t = (DWT->CYCCNT * 1000llu + ippms2) / ippms; - if (ret & ACC_DATA_READY) { - cardboard::AccelerometerData adata - = { .system_timestamp = t, .sensor_timestamp_ns = t, - .data = cardboard::Vector3(vec[0], vec[1], vec[2]) }; - tracker.OnAccelerometerData(adata); - } - if (ret & GYR_DATA_READY) { - cardboard::GyroscopeData gdata - = { .system_timestamp = t, .sensor_timestamp_ns = t, - .data = cardboard::Vector3(vec[3], vec[4], vec[5]) }; - cardboard::Vector4 pose = tracker.OnGyroscopeData(gdata); - onOrientation(pose); - sendCurrentState(mouse_move, context); - } - } + g_state.stepTracking(mouse_move, context); } void tracking_end() { - tracker.Pause(); + g_state.stopTracking(); } } diff --git a/applications/external/airmouse/tracking/orientation_tracker.cc b/applications/external/airmouse/tracking/orientation_tracker.cc index ac20e9672..4f381c895 100644 --- a/applications/external/airmouse/tracking/orientation_tracker.cc +++ b/applications/external/airmouse/tracking/orientation_tracker.cc @@ -89,7 +89,7 @@ Vector4 OrientationTracker::OnGyroscopeData(const GyroscopeData& event) sensor_fusion_->ProcessGyroscopeSample(data); - return OrientationTracker::GetPose(data.sensor_timestamp_ns + sampling_period_ns_); + return GetPose(data.sensor_timestamp_ns + sampling_period_ns_); } } // namespace cardboard diff --git a/applications/external/airmouse/tracking/sensors/sensor_fusion_ekf.cc b/applications/external/airmouse/tracking/sensors/sensor_fusion_ekf.cc index 575dde6f0..dabd788ef 100644 --- a/applications/external/airmouse/tracking/sensors/sensor_fusion_ekf.cc +++ b/applications/external/airmouse/tracking/sensors/sensor_fusion_ekf.cc @@ -59,13 +59,14 @@ namespace { // angle = norm(a) // axis = a.normalized() // If norm(a) == 0, it returns an identity rotation. - static inline Rotation RotationFromVector(const Vector3& a) + static inline void RotationFromVector(const Vector3& a, Rotation& r) { const double norm_a = Length(a); if (norm_a < kEpsilon) { - return Rotation::Identity(); + r = Rotation::Identity(); + return; } - return Rotation::FromAxisAndAngle(a / norm_a, norm_a); + r = Rotation::FromAxisAndAngle(a / norm_a, norm_a); } } // namespace @@ -199,7 +200,8 @@ void SensorFusionEkf::ComputeMeasurementJacobian() Vector3 delta = Vector3::Zero(); delta[dof] = kFiniteDifferencingEpsilon; - const Rotation epsilon_rotation = RotationFromVector(delta); + Rotation epsilon_rotation; + RotationFromVector(delta, epsilon_rotation); const Vector3 delta_rotation = ComputeInnovation(epsilon_rotation * current_state_.sensor_from_start_rotation); @@ -263,7 +265,8 @@ void SensorFusionEkf::ProcessAccelerometerSample(const AccelerometerData& sample * state_covariance_; // Updates pose and associate covariance matrix. - const Rotation rotation_from_state_update = RotationFromVector(state_update_); + Rotation rotation_from_state_update; + RotationFromVector(state_update_, rotation_from_state_update); current_state_.sensor_from_start_rotation = rotation_from_state_update * current_state_.sensor_from_start_rotation; diff --git a/applications/external/airmouse/views/bt_mouse.c b/applications/external/airmouse/views/bt_mouse.c index 7d9c0e6db..664b25bfd 100644 --- a/applications/external/airmouse/views/bt_mouse.c +++ b/applications/external/airmouse/views/bt_mouse.c @@ -132,6 +132,11 @@ void bt_mouse_connection_status_changed_callback(BtStatus status, void* context) BtMouse* bt_mouse = context; bt_mouse->connected = (status == BtStatusConnected); + if(!bt_mouse->notifications) { + tracking_end(); + return; + } + if(bt_mouse->connected) { notification_internal_message(bt_mouse->notifications, &sequence_set_blue_255); tracking_begin(); @@ -140,9 +145,6 @@ void bt_mouse_connection_status_changed_callback(BtStatus status, void* context) tracking_end(); notification_internal_message(bt_mouse->notifications, &sequence_reset_blue); } - - //with_view_model( - // bt_mouse->view, void * model, { model->connected = connected; }, true); } bool bt_mouse_move(int8_t dx, int8_t dy, void* context) { @@ -160,46 +162,6 @@ bool bt_mouse_move(int8_t dx, int8_t dy, void* context) { return true; } -void bt_mouse_enter_callback(void* context) { - furi_assert(context); - BtMouse* bt_mouse = context; - - bt_mouse->bt = furi_record_open(RECORD_BT); - bt_mouse->notifications = furi_record_open(RECORD_NOTIFICATION); - bt_set_status_changed_callback( - bt_mouse->bt, bt_mouse_connection_status_changed_callback, bt_mouse); - furi_assert(bt_set_profile(bt_mouse->bt, BtProfileHidKeyboard)); - furi_hal_bt_start_advertising(); -} - -bool bt_mouse_custom_callback(uint32_t event, void* context) { - UNUSED(event); - furi_assert(context); - BtMouse* bt_mouse = context; - - tracking_step(bt_mouse_move, context); - furi_delay_ms(3); // Magic! Removing this will break the buttons - - view_dispatcher_send_custom_event(bt_mouse->view_dispatcher, 0); - return true; -} - -void bt_mouse_exit_callback(void* context) { - furi_assert(context); - BtMouse* bt_mouse = context; - - tracking_end(); - notification_internal_message(bt_mouse->notifications, &sequence_reset_blue); - - furi_hal_bt_stop_advertising(); - bt_set_profile(bt_mouse->bt, BtProfileSerial); - - furi_record_close(RECORD_NOTIFICATION); - bt_mouse->notifications = NULL; - furi_record_close(RECORD_BT); - bt_mouse->bt = NULL; -} - static int8_t clamp(int t) { if(t < -128) { return -128; @@ -279,6 +241,50 @@ void bt_mouse_thread_stop(BtMouse* bt_mouse) { furi_thread_join(bt_mouse->thread); furi_thread_free(bt_mouse->thread); furi_mutex_free(bt_mouse->mutex); + bt_mouse->mutex = NULL; + bt_mouse->thread = NULL; +} + +void bt_mouse_enter_callback(void* context) { + furi_assert(context); + BtMouse* bt_mouse = context; + + bt_mouse->bt = furi_record_open(RECORD_BT); + bt_mouse->notifications = furi_record_open(RECORD_NOTIFICATION); + bt_set_status_changed_callback( + bt_mouse->bt, bt_mouse_connection_status_changed_callback, bt_mouse); + furi_assert(bt_set_profile(bt_mouse->bt, BtProfileHidKeyboard)); + furi_hal_bt_start_advertising(); + bt_mouse_thread_start(bt_mouse); +} + +bool bt_mouse_custom_callback(uint32_t event, void* context) { + UNUSED(event); + furi_assert(context); + BtMouse* bt_mouse = context; + + tracking_step(bt_mouse_move, context); + furi_delay_ms(3); // Magic! Removing this will break the buttons + + view_dispatcher_send_custom_event(bt_mouse->view_dispatcher, 0); + return true; +} + +void bt_mouse_exit_callback(void* context) { + furi_assert(context); + BtMouse* bt_mouse = context; + + bt_mouse_thread_stop(bt_mouse); + tracking_end(); + notification_internal_message(bt_mouse->notifications, &sequence_reset_blue); + + furi_hal_bt_stop_advertising(); + bt_set_profile(bt_mouse->bt, BtProfileSerial); + + furi_record_close(RECORD_NOTIFICATION); + bt_mouse->notifications = NULL; + furi_record_close(RECORD_BT); + bt_mouse->bt = NULL; } BtMouse* bt_mouse_alloc(ViewDispatcher* view_dispatcher) { @@ -293,13 +299,11 @@ BtMouse* bt_mouse_alloc(ViewDispatcher* view_dispatcher) { view_set_enter_callback(bt_mouse->view, bt_mouse_enter_callback); view_set_custom_callback(bt_mouse->view, bt_mouse_custom_callback); view_set_exit_callback(bt_mouse->view, bt_mouse_exit_callback); - bt_mouse_thread_start(bt_mouse); return bt_mouse; } void bt_mouse_free(BtMouse* bt_mouse) { furi_assert(bt_mouse); - bt_mouse_thread_stop(bt_mouse); view_free(bt_mouse->view); free(bt_mouse); } diff --git a/applications/external/arkanoid/application.fam b/applications/external/arkanoid/application.fam index b33b9acae..19e851514 100644 --- a/applications/external/arkanoid/application.fam +++ b/applications/external/arkanoid/application.fam @@ -5,7 +5,6 @@ App( entry_point="arkanoid_game_app", requires=["gui"], stack_size=1 * 1024, - order=20, fap_icon="arkanoid_10px.png", fap_category="Games", fap_author="@xMasterX & @gotnull", diff --git a/applications/external/arkanoid/arkanoid_game.c b/applications/external/arkanoid/arkanoid_game.c index f6d8c1a3d..2adf2e30b 100644 --- a/applications/external/arkanoid/arkanoid_game.c +++ b/applications/external/arkanoid/arkanoid_game.c @@ -5,6 +5,7 @@ #include #include #include +#include #define TAG "Arkanoid" @@ -397,6 +398,9 @@ int32_t arkanoid_game_app(void* p) { Gui* gui = furi_record_open(RECORD_GUI); gui_add_view_port(gui, view_port, GuiLayerFullscreen); + // Call dolphin deed on game start + dolphin_deed(DolphinDeedPluginGameStart); + GameEvent event; for(bool processing = true; processing;) { FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); diff --git a/applications/external/asteroids/application.fam b/applications/external/asteroids/application.fam index ca5f5d175..608809c02 100644 --- a/applications/external/asteroids/application.fam +++ b/applications/external/asteroids/application.fam @@ -6,7 +6,6 @@ App( cdefines=["APP_ASTEROIDS"], requires=["gui"], stack_size=8 * 1024, - order=50, fap_icon="appicon.png", fap_icon_assets="assets", fap_category="Games", diff --git a/applications/external/avr_isp_programmer/application.fam b/applications/external/avr_isp_programmer/application.fam index 5f3b17037..f355cfcb5 100644 --- a/applications/external/avr_isp_programmer/application.fam +++ b/applications/external/avr_isp_programmer/application.fam @@ -5,7 +5,8 @@ App( entry_point="avr_isp_app", requires=["gui"], stack_size=4 * 1024, - order=20, + fap_description="Application for flashing AVR microcontrollers", + fap_version="1.0", fap_icon="avr_app_icon_10x10.png", fap_category="GPIO", fap_icon_assets="images", diff --git a/applications/external/avr_isp_programmer/avr_isp_app_i.h b/applications/external/avr_isp_programmer/avr_isp_app_i.h index 819e3f45f..8a7dbc4b8 100644 --- a/applications/external/avr_isp_programmer/avr_isp_app_i.h +++ b/applications/external/avr_isp_programmer/avr_isp_app_i.h @@ -1,7 +1,8 @@ #pragma once #include "helpers/avr_isp_types.h" -#include +#include "avr_isp_icons.h" +#include #include "scenes/avr_isp_scene.h" #include @@ -41,4 +42,4 @@ typedef struct { AvrIspError error; } AvrIspApp; -bool avr_isp_load_from_file(AvrIspApp* app); +bool avr_isp_load_from_file(AvrIspApp* app); \ No newline at end of file diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp.c b/applications/external/avr_isp_programmer/helpers/avr_isp.c index 1b9e2fd1f..283c17bfd 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp.c @@ -174,7 +174,7 @@ static void avr_isp_commit(AvrIsp* instance, uint16_t addr, uint8_t data) { while((furi_get_tick() - starttime) < 30) { if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FLASH_HI(addr)) != 0xFF) { break; - } + }; } } } @@ -357,7 +357,7 @@ uint8_t avr_isp_read_lock_byte(AvrIsp* instance) { data = avr_isp_spi_transaction(instance, AVR_ISP_READ_LOCK_BYTE); if(avr_isp_spi_transaction(instance, AVR_ISP_READ_LOCK_BYTE) == data) { break; - } + }; data = 0x00; } return data; @@ -377,7 +377,7 @@ bool avr_isp_write_lock_byte(AvrIsp* instance, uint8_t lock) { if(avr_isp_spi_transaction(instance, AVR_ISP_READ_LOCK_BYTE) == lock) { ret = true; break; - } + }; } } return ret; @@ -392,7 +392,7 @@ uint8_t avr_isp_read_fuse_low(AvrIsp* instance) { data = avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_LOW); if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_LOW) == data) { break; - } + }; data = 0x00; } return data; @@ -412,7 +412,7 @@ bool avr_isp_write_fuse_low(AvrIsp* instance, uint8_t lfuse) { if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_LOW) == lfuse) { ret = true; break; - } + }; } } return ret; @@ -427,7 +427,7 @@ uint8_t avr_isp_read_fuse_high(AvrIsp* instance) { data = avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_HIGH); if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_HIGH) == data) { break; - } + }; data = 0x00; } return data; @@ -447,7 +447,7 @@ bool avr_isp_write_fuse_high(AvrIsp* instance, uint8_t hfuse) { if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_HIGH) == hfuse) { ret = true; break; - } + }; } } return ret; @@ -462,7 +462,7 @@ uint8_t avr_isp_read_fuse_extended(AvrIsp* instance) { data = avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_EXTENDED); if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_EXTENDED) == data) { break; - } + }; data = 0x00; } return data; @@ -482,7 +482,7 @@ bool avr_isp_write_fuse_extended(AvrIsp* instance, uint8_t efuse) { if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_EXTENDED) == efuse) { ret = true; break; - } + }; } } return ret; diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c index 121f08565..b4c12cbc3 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c @@ -350,12 +350,12 @@ static void avr_isp_worker_rw_get_dump_flash(AvrIspWorkerRW* instance, const cha sizeof(data)); flipper_i32hex_file_bin_to_i32hex_set_data( flipper_hex_flash, data, avr_isp_chip_arr[instance->chip_arr_ind].pagesize); - //FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash)); + FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash)); instance->progress_flash = (float)(i) / ((float)avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2.0f); } flipper_i32hex_file_bin_to_i32hex_set_end_line(flipper_hex_flash); - //FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash)); + FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash)); flipper_i32hex_file_close(flipper_hex_flash); instance->progress_flash = 1.0f; } diff --git a/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c b/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c index 051d97e9c..bbb6d4739 100644 --- a/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c +++ b/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c @@ -111,7 +111,7 @@ static uint8_t avr_isp_prog_getch(AvrIspProg* instance) { uint8_t data[1] = {0}; while(furi_stream_buffer_receive(instance->stream_rx, &data, sizeof(int8_t), 30) == 0) { if(instance->exit) break; - } + }; return data[0]; } @@ -196,7 +196,7 @@ static void avr_isp_prog_set_cfg(AvrIspProg* instance) { instance->cfg->lockbytes = instance->buff[6]; instance->cfg->fusebytes = instance->buff[7]; instance->cfg->flashpoll = instance->buff[8]; - // ignore (instance->buff[9] == instance->buff[8]) //FLASH polling value. Same as �flashpoll� + // ignore (instance->buff[9] == instance->buff[8]) //FLASH polling value. Same as flashpoll instance->cfg->eeprompoll = instance->buff[10] << 8 | instance->buff[11]; instance->cfg->pagesize = instance->buff[12] << 8 | instance->buff[13]; instance->cfg->eepromsize = instance->buff[14] << 8 | instance->buff[15]; @@ -348,7 +348,7 @@ static void avr_isp_prog_commit(AvrIspProg* instance, uint16_t addr, uint8_t dat while((furi_get_tick() - starttime) < 30) { if(avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_FLASH_HI(addr)) != 0xFF) { break; - } + }; } } } diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c index fdcf71c36..b30d4e916 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c @@ -1,5 +1,6 @@ #include "avr_isp_view_chip_detect.h" -#include +#include "avr_isp_icons.h" +#include #include #include "../helpers/avr_isp_worker_rw.h" diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c b/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c index 34e18770b..38b7394d6 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c @@ -1,5 +1,6 @@ #include "avr_isp_view_programmer.h" -#include +#include "avr_isp_icons.h" +#include #include "../helpers/avr_isp_worker.h" #include diff --git a/applications/external/barcode_gen/barcode_app.c b/applications/external/barcode_gen/barcode_app.c index 99e5769d2..aff437f2e 100644 --- a/applications/external/barcode_gen/barcode_app.c +++ b/applications/external/barcode_gen/barcode_app.c @@ -1,6 +1,7 @@ #include "barcode_app.h" #include "barcode_app_icons.h" +#include /** * Opens a file browser dialog and returns the filepath of the selected file diff --git a/applications/external/blackjack/application.fam b/applications/external/blackjack/application.fam index 83b3c83a8..504989116 100644 --- a/applications/external/blackjack/application.fam +++ b/applications/external/blackjack/application.fam @@ -5,7 +5,6 @@ App( entry_point="blackjack_app", requires=["gui", "storage", "canvas"], stack_size=2 * 1024, - order=30, fap_icon="blackjack_10px.png", fap_category="Games", fap_icon_assets="assets", diff --git a/applications/external/blackjack/blackjack.c b/applications/external/blackjack/blackjack.c index ee5e35415..8cf698d85 100644 --- a/applications/external/blackjack/blackjack.c +++ b/applications/external/blackjack/blackjack.c @@ -1,6 +1,7 @@ #include #include +#include #include #include @@ -14,6 +15,7 @@ #include "ui.h" #include "blackjack_icons.h" +#include #define DEALER_MAX 17 @@ -275,6 +277,7 @@ void dealer_tick(GameState* game_state) { if(dealer_score >= DEALER_MAX) { if(dealer_score > 21 || dealer_score < player_score) { + dolphin_deed(DolphinDeedPluginGameWin); enqueue( &(game_state->queue_state), game_state, @@ -568,6 +571,9 @@ int32_t blackjack_app(void* p) { AppEvent event; + // Call dolphin deed on game start + dolphin_deed(DolphinDeedPluginGameStart); + for(bool processing = true; processing;) { FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); furi_mutex_acquire(game_state->mutex, FuriWaitForever); @@ -625,4 +631,4 @@ free_and_exit: furi_message_queue_free(event_queue); return return_code; -} +} \ No newline at end of file diff --git a/applications/external/bomberduck/application.fam b/applications/external/bomberduck/application.fam index 39c680693..958ac7c02 100644 --- a/applications/external/bomberduck/application.fam +++ b/applications/external/bomberduck/application.fam @@ -7,7 +7,6 @@ App( "gui", ], stack_size=1 * 1024, - order=90, fap_icon="bomb.png", fap_category="Games", fap_icon_assets="assets", diff --git a/applications/external/bomberduck/bomberduck.c b/applications/external/bomberduck/bomberduck.c index d81515371..eddec089f 100644 --- a/applications/external/bomberduck/bomberduck.c +++ b/applications/external/bomberduck/bomberduck.c @@ -6,6 +6,8 @@ #include #include #include "bomberduck_icons.h" +#include +#include int max(int a, int b) { return (a > b) ? a : b; @@ -381,6 +383,7 @@ int32_t bomberduck_app(void* p) { return 255; } + dolphin_deed(DolphinDeedPluginGameStart); // Создаем новый view port ViewPort* view_port = view_port_alloc(); // Создаем callback отрисовки, без контекста @@ -454,8 +457,9 @@ int32_t bomberduck_app(void* p) { notification_message(notification, &end); world.running = 0; world.level += 1; - // if(world.level % 5 == 0) { - // } + if(world.level % 5 == 0) { + dolphin_deed(DolphinDeedPluginGameWin); + } } for(int i = 0; i < world.bombs_count; i++) { if(furi_get_tick() - world.bombs[i].planted > diff --git a/applications/external/bpmtapper/application.fam b/applications/external/bpmtapper/application.fam index bf3f3c895..b25f61af3 100644 --- a/applications/external/bpmtapper/application.fam +++ b/applications/external/bpmtapper/application.fam @@ -9,7 +9,6 @@ App( fap_icon="bpm_10px.png", fap_category="Media", fap_icon_assets="icons", - order=15, fap_author="@panki27", fap_weburl="https://github.com/panki27/bpm-tapper", fap_version="1.0", diff --git a/applications/external/caesarcipher/application.fam b/applications/external/caesarcipher/application.fam index fdb1052b0..985487986 100644 --- a/applications/external/caesarcipher/application.fam +++ b/applications/external/caesarcipher/application.fam @@ -10,7 +10,6 @@ App( stack_size=2 * 1024, fap_icon="caesar_cipher_icon.png", fap_category="Tools", - order=20, fap_author="@panki27", fap_weburl="https://github.com/panki27/caesar-cipher", fap_version="1.0", diff --git a/applications/external/calculator/application.fam b/applications/external/calculator/application.fam index cba45e49b..cfd183ec3 100644 --- a/applications/external/calculator/application.fam +++ b/applications/external/calculator/application.fam @@ -6,7 +6,6 @@ App( cdefines=["APP_CALCULATOR"], requires=["gui"], stack_size=1 * 1024, - order=45, fap_icon="calcIcon.png", fap_category="Tools", fap_author="@n-o-T-I-n-s-a-n-e", diff --git a/applications/external/camera_suite/application.fam b/applications/external/camera_suite/application.fam index d3ddde2c1..1c9f0cc6f 100644 --- a/applications/external/camera_suite/application.fam +++ b/applications/external/camera_suite/application.fam @@ -9,7 +9,6 @@ App( fap_icon="icons/camera_suite.png", fap_weburl="https://github.com/CodyTolene/Flipper-Zero-Cam", name="[ESP32] Camera Suite", - order=1, requires=["gui", "storage"], stack_size=8 * 1024, ) diff --git a/applications/external/camera_suite/views/camera_suite_view_camera.c b/applications/external/camera_suite/views/camera_suite_view_camera.c index 77850b425..94b8a8639 100644 --- a/applications/external/camera_suite/views/camera_suite_view_camera.c +++ b/applications/external/camera_suite/views/camera_suite_view_camera.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "../helpers/camera_suite_haptic.h" #include "../helpers/camera_suite_speaker.h" #include "../helpers/camera_suite_led.h" diff --git a/applications/external/camera_suite/views/camera_suite_view_guide.c b/applications/external/camera_suite/views/camera_suite_view_guide.c index b32b0dd8f..479f8d4d1 100644 --- a/applications/external/camera_suite/views/camera_suite_view_guide.c +++ b/applications/external/camera_suite/views/camera_suite_view_guide.c @@ -3,6 +3,7 @@ #include #include #include +#include struct CameraSuiteViewGuide { View* view; diff --git a/applications/external/chess/application.fam b/applications/external/chess/application.fam index e0479c380..6f3d3321c 100644 --- a/applications/external/chess/application.fam +++ b/applications/external/chess/application.fam @@ -7,7 +7,6 @@ App( "gui", ], stack_size=4 * 1024, - order=10, fap_icon="flipchess_10px.png", fap_icon_assets="icons", fap_icon_assets_symbol="flipchess", diff --git a/applications/external/chess/icons/Background_128x11.png b/applications/external/chess/icons/Background_128x11.png deleted file mode 100644 index 149780f0c..000000000 Binary files a/applications/external/chess/icons/Background_128x11.png and /dev/null differ diff --git a/applications/external/chess/views/flipchess_startscreen.c b/applications/external/chess/views/flipchess_startscreen.c index d25bbe2cc..9a146674e 100644 --- a/applications/external/chess/views/flipchess_startscreen.c +++ b/applications/external/chess/views/flipchess_startscreen.c @@ -4,6 +4,7 @@ #include #include #include "flipchess_icons.h" +#include struct FlipChessStartscreen { View* view; diff --git a/applications/external/cntdown_timer/application.fam b/applications/external/cntdown_timer/application.fam index 054833eeb..79a08423e 100644 --- a/applications/external/cntdown_timer/application.fam +++ b/applications/external/cntdown_timer/application.fam @@ -10,7 +10,6 @@ App( "gui", ], stack_size=2 * 1024, - order=20, fap_icon="cntdown_timer.png", fap_category="Tools", fap_author="@0w0mewo", diff --git a/applications/external/dap_link/application.fam b/applications/external/dap_link/application.fam index e05a7e01f..8f25bef83 100644 --- a/applications/external/dap_link/application.fam +++ b/applications/external/dap_link/application.fam @@ -8,7 +8,8 @@ App( "dialogs", ], stack_size=4 * 1024, - order=20, + fap_description="Enables use of Flipper as a debug probe for ARM devices, implements the CMSIS-DAP protocol", + fap_version="1.0", fap_icon="dap_link.png", fap_category="GPIO", fap_private_libs=[ diff --git a/applications/external/dap_link/dap_link.c b/applications/external/dap_link/dap_link.c index 52d222138..487c63c44 100644 --- a/applications/external/dap_link/dap_link.c +++ b/applications/external/dap_link/dap_link.c @@ -15,7 +15,7 @@ #include "usb/dap_v2_usb.h" #include #include "dap_link_icons.h" -#include "assets_icons.h" +#include /***************************************************************************/ /****************************** DAP COMMON *********************************/ @@ -525,4 +525,4 @@ int32_t dap_link_app(void* p) { dap_app_free(app); return 0; -} +} \ No newline at end of file diff --git a/applications/external/dap_link/gui/views/dap_main_view.c b/applications/external/dap_link/gui/views/dap_main_view.c index f54c5e3d5..15f285698 100644 --- a/applications/external/dap_link/gui/views/dap_main_view.c +++ b/applications/external/dap_link/gui/views/dap_main_view.c @@ -1,5 +1,6 @@ #include "dap_main_view.h" #include "dap_link_icons.h" +#include #include // extern const Icon I_ArrowDownEmpty_12x18; diff --git a/applications/external/doom/.gitignore b/applications/external/doom/.gitignore deleted file mode 100644 index e2a15a10a..000000000 --- a/applications/external/doom/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -dist/* -.vscode -.clang-format -.editorconfig \ No newline at end of file diff --git a/applications/external/doom/application.fam b/applications/external/doom/application.fam index 5ff6878ee..995286d74 100644 --- a/applications/external/doom/application.fam +++ b/applications/external/doom/application.fam @@ -8,7 +8,6 @@ App( "music_player", ], stack_size=4 * 1024, - order=75, fap_icon="doom_10px.png", fap_category="Games", fap_icon_assets="assets", diff --git a/applications/external/doom/display.h b/applications/external/doom/display.h index 89f821867..a949b14fa 100644 --- a/applications/external/doom/display.h +++ b/applications/external/doom/display.h @@ -1,7 +1,8 @@ #include #include #include "constants.h" -#include +#include "doom_icons.h" +#include #include "assets.h" #define CHECK_BIT(var, pos) ((var) & (1 << (pos))) diff --git a/applications/external/doom/doom.c b/applications/external/doom/doom.c index dfe37d094..c2d9a6bf0 100644 --- a/applications/external/doom/doom.c +++ b/applications/external/doom/doom.c @@ -13,6 +13,7 @@ #include "level.h" #include #include +#include #define SOUND @@ -156,9 +157,6 @@ void spawnEntity(uint8_t type, uint8_t x, uint8_t y, PluginState* const plugin_s plugin_state->entity[plugin_state->num_entities] = create_medikit(x, y); plugin_state->num_entities++; break; - - default: - break; } } @@ -462,9 +460,6 @@ void updateEntities(const uint8_t level[], Canvas* const canvas, PluginState* co } break; } - - default: - break; } i++; @@ -993,6 +988,9 @@ int32_t doom_app() { music_player_worker_load_rtttl_from_string(plugin_state->music_instance->worker, dsintro); music_player_worker_start(plugin_state->music_instance->worker); #endif + // Call dolphin deed on game start + dolphin_deed(DolphinDeedPluginGameStart); + for(bool processing = true; processing;) { FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); furi_mutex_acquire(plugin_state->mutex, FuriWaitForever); diff --git a/applications/external/doom/doom_music_player_worker.c b/applications/external/doom/doom_music_player_worker.c index c8b9bb9db..e81549625 100644 --- a/applications/external/doom/doom_music_player_worker.c +++ b/applications/external/doom/doom_music_player_worker.c @@ -393,7 +393,7 @@ bool music_player_worker_load_rtttl_from_file(MusicPlayerWorker* instance, const if(!storage_file_open(file, file_path, FSAM_READ, FSOM_OPEN_EXISTING)) { FURI_LOG_E(TAG, "Unable to open file"); break; - } + }; uint16_t ret = 0; do { diff --git a/applications/external/dtmf_dolphin/application.fam b/applications/external/dtmf_dolphin/application.fam index 5f01bc9a0..11a72df12 100644 --- a/applications/external/dtmf_dolphin/application.fam +++ b/applications/external/dtmf_dolphin/application.fam @@ -10,9 +10,8 @@ App( ], fap_icon="phone.png", stack_size=8 * 1024, - order=20, fap_category="Tools", fap_author="@litui & @xMasterX", - fap_version="1.0", + fap_version="1.1", fap_description="DTMF (Dual-Tone Multi-Frequency) dialer, Bluebox, and Redbox.", ) diff --git a/applications/external/dtmf_dolphin/dtmf_dolphin.c b/applications/external/dtmf_dolphin/dtmf_dolphin.c index 698b23540..c1b10defa 100644 --- a/applications/external/dtmf_dolphin/dtmf_dolphin.c +++ b/applications/external/dtmf_dolphin/dtmf_dolphin.c @@ -86,4 +86,4 @@ int32_t dtmf_dolphin_app(void* p) { app_free(app); return 0; -} +} \ No newline at end of file diff --git a/applications/external/dtmf_dolphin/phone.png b/applications/external/dtmf_dolphin/phone.png index 443f847c3..9c4d04c02 100644 Binary files a/applications/external/dtmf_dolphin/phone.png and b/applications/external/dtmf_dolphin/phone.png differ diff --git a/applications/external/esp32cam_camera/application.fam b/applications/external/esp32cam_camera/application.fam index a0e0ede4c..e8d5c7158 100644 --- a/applications/external/esp32cam_camera/application.fam +++ b/applications/external/esp32cam_camera/application.fam @@ -6,7 +6,6 @@ App( cdefines=["APP_CAMERA"], requires=["gui"], stack_size=8 * 1024, - order=1, fap_icon="icon.png", fap_category="GPIO", fap_description="ESP32-CAM live feed and photo capture, use left/right for orientation/mode, up/down for brightness and center for saving a screenshot. [Unplug the USB cable to test with Mayhem]", diff --git a/applications/external/esp32cam_evilportal/application.fam b/applications/external/esp32cam_evilportal/application.fam index 190ae711a..d842ddc79 100644 --- a/applications/external/esp32cam_evilportal/application.fam +++ b/applications/external/esp32cam_evilportal/application.fam @@ -6,7 +6,6 @@ App( cdefines=["APP_EVIL_PORTAL"], requires=["gui"], stack_size=1 * 1024, - order=90, fap_icon="icons/evil_portal_10px.png", fap_category="GPIO", fap_description="ESP32-CAM evil portal. When users try to connect to this access point they will be served a fake login screen. User credentials are sent to the Flipper and logged on the SD card. [Unplug the USB cable to test with Mayhem]", diff --git a/applications/external/esp32cam_marauder_companion/application.fam b/applications/external/esp32cam_marauder_companion/application.fam index 800cb92be..891c0859d 100644 --- a/applications/external/esp32cam_marauder_companion/application.fam +++ b/applications/external/esp32cam_marauder_companion/application.fam @@ -6,7 +6,6 @@ App( cdefines=["APP_WIFI_MARAUDER"], requires=["gui"], stack_size=4 * 1024, - order=2, fap_icon="wifi_10px.png", fap_category="GPIO", fap_description="ESP32-CAM version of Marauder. Includes all functionality from the original plus some options to trigger the camera and flashlight. [Unplug the USB cable to test with Mayhem]", diff --git a/applications/external/esp32cam_morseflasher/application.fam b/applications/external/esp32cam_morseflasher/application.fam index 037e63c81..4c40e19a9 100644 --- a/applications/external/esp32cam_morseflasher/application.fam +++ b/applications/external/esp32cam_morseflasher/application.fam @@ -6,7 +6,6 @@ App( cdefines=["APP_UART_TERMINAL"], requires=["gui"], stack_size=1 * 1024, - order=90, fap_icon_assets="assets", fap_icon="icon.png", fap_category="GPIO", diff --git a/applications/external/esp32cam_motion_detection/application.fam b/applications/external/esp32cam_motion_detection/application.fam index 57a5396c5..b2fa8a467 100644 --- a/applications/external/esp32cam_motion_detection/application.fam +++ b/applications/external/esp32cam_motion_detection/application.fam @@ -6,7 +6,6 @@ App( cdefines=["APP_QRCODE"], requires=["gui"], stack_size=8 * 1024, - order=1, fap_icon="icon.png", fap_category="GPIO", fap_description="ESP32-CAM Motion detection. It generates a beep when motion is detected. Can be extended to trigger more stuff in the code. [Unplug the USB cable to test with Mayhem]", diff --git a/applications/external/esp32cam_nannycam/application.fam b/applications/external/esp32cam_nannycam/application.fam index 75f2be783..bbb7022d1 100644 --- a/applications/external/esp32cam_nannycam/application.fam +++ b/applications/external/esp32cam_nannycam/application.fam @@ -6,7 +6,6 @@ App( cdefines=["APP_QRCODE"], requires=["gui"], stack_size=8 * 1024, - order=1, fap_icon="icon.png", fap_category="GPIO", fap_description="ESP32-CAM simple app to start a remote camera. [Unplug the USB cable to test with Mayhem]", diff --git a/applications/external/esp32cam_qrcode/application.fam b/applications/external/esp32cam_qrcode/application.fam index 73c418510..b96942e9e 100644 --- a/applications/external/esp32cam_qrcode/application.fam +++ b/applications/external/esp32cam_qrcode/application.fam @@ -6,7 +6,6 @@ App( cdefines=["APP_QRCODE"], requires=["gui"], stack_size=8 * 1024, - order=1, fap_icon="icon.png", fap_category="GPIO", fap_description="ESP32-CAM simple app to show a payload from QR codes. Can be extended to trigger more stuff in the code. [Unplug the USB cable to test with Mayhem]", diff --git a/applications/external/esp8266_deauth/application.fam b/applications/external/esp8266_deauth/application.fam index 9b176a3dd..f36d85d18 100644 --- a/applications/external/esp8266_deauth/application.fam +++ b/applications/external/esp8266_deauth/application.fam @@ -5,7 +5,6 @@ App( entry_point="esp8266_deauth_app", requires=["gui"], stack_size=2 * 1024, - order=100, fap_icon="wifi_10px.png", fap_category="WiFi", fap_author="@SequoiaSan & @xMasterX", diff --git a/applications/external/esp_flasher/application.fam b/applications/external/esp_flasher/application.fam index 2a3085511..1fd1c6e7a 100644 --- a/applications/external/esp_flasher/application.fam +++ b/applications/external/esp_flasher/application.fam @@ -6,7 +6,6 @@ App( entry_point="esp_flasher_app", requires=["gui"], stack_size=4 * 1024, - order=90, fap_icon="update_10px.png", fap_category="GPIO", fap_private_libs=[ diff --git a/applications/external/esubghz_chat/assets/Nfc_14px.png b/applications/external/esubghz_chat/assets/Nfc_14px.png new file mode 100644 index 000000000..9e43a3291 Binary files /dev/null and b/applications/external/esubghz_chat/assets/Nfc_14px.png differ diff --git a/applications/external/esubghz_chat/assets/chat_14px.png b/applications/external/esubghz_chat/assets/chat_14px.png new file mode 100644 index 000000000..f949d0a79 Binary files /dev/null and b/applications/external/esubghz_chat/assets/chat_14px.png differ diff --git a/applications/external/esubghz_chat/assets/hex_10px.png b/applications/external/esubghz_chat/assets/hex_10px.png deleted file mode 100644 index 582e288c6..000000000 Binary files a/applications/external/esubghz_chat/assets/hex_10px.png and /dev/null differ diff --git a/applications/external/esubghz_chat/assets/hex_14px.png b/applications/external/esubghz_chat/assets/hex_14px.png new file mode 100644 index 000000000..b2af9e204 Binary files /dev/null and b/applications/external/esubghz_chat/assets/hex_14px.png differ diff --git a/applications/external/esubghz_chat/assets/keyboard_14px.png b/applications/external/esubghz_chat/assets/keyboard_14px.png new file mode 100644 index 000000000..b84309c5a Binary files /dev/null and b/applications/external/esubghz_chat/assets/keyboard_14px.png differ diff --git a/applications/external/esubghz_chat/assets/u2f_14px.png b/applications/external/esubghz_chat/assets/u2f_14px.png new file mode 100644 index 000000000..d65bacea9 Binary files /dev/null and b/applications/external/esubghz_chat/assets/u2f_14px.png differ diff --git a/applications/external/esubghz_chat/crypto_wrapper.c b/applications/external/esubghz_chat/crypto_wrapper.c index e9074bdce..5d72bd843 100644 --- a/applications/external/esubghz_chat/crypto_wrapper.c +++ b/applications/external/esubghz_chat/crypto_wrapper.c @@ -192,10 +192,46 @@ bool crypto_ctx_encrypt(ESubGhzChatCryptoCtx* ctx, uint8_t* in, size_t in_len, u TAG_BYTES) == 0); #endif /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */ - // increase internal counter + // update replay dict and increase internal counter if(ret) { + ESubGhzChatReplayDict_set_at(ctx->replay_dict, ctx->run_id, ctx->counter); ctx->counter++; } return ret; } + +size_t crypto_ctx_dump_replay_dict( + ESubGhzChatCryptoCtx* ctx, + CryptoCtxReplayDictWriter writer, + void* writer_ctx) { + size_t ret = 0; + ESubGhzChatReplayDict_it_t i; + + for(ESubGhzChatReplayDict_it(i, ctx->replay_dict); !ESubGhzChatReplayDict_end_p(i); + ESubGhzChatReplayDict_next(i), ret++) { + ESubGhzChatReplayDict_itref_t* ref = ESubGhzChatReplayDict_ref(i); + if(!writer(ref->key, ref->value, writer_ctx)) { + break; + } + } + + return ret; +} + +size_t crypto_ctx_read_replay_dict( + ESubGhzChatCryptoCtx* ctx, + CryptoCtxReplayDictReader reader, + void* reader_ctx) { + size_t ret = 0; + + uint64_t run_id; + uint32_t counter; + + while(reader(&run_id, &counter, reader_ctx)) { + ESubGhzChatReplayDict_set_at(ctx->replay_dict, run_id, counter); + ret++; + } + + return ret; +} diff --git a/applications/external/esubghz_chat/crypto_wrapper.h b/applications/external/esubghz_chat/crypto_wrapper.h index 4a3dcf8e5..080a604d1 100644 --- a/applications/external/esubghz_chat/crypto_wrapper.h +++ b/applications/external/esubghz_chat/crypto_wrapper.h @@ -34,6 +34,18 @@ void crypto_ctx_get_key(ESubGhzChatCryptoCtx* ctx, uint8_t* key); bool crypto_ctx_decrypt(ESubGhzChatCryptoCtx* ctx, uint8_t* in, size_t in_len, uint8_t* out); bool crypto_ctx_encrypt(ESubGhzChatCryptoCtx* ctx, uint8_t* in, size_t in_len, uint8_t* out); +typedef bool (*CryptoCtxReplayDictWriter)(uint64_t run_id, uint32_t counter, void* context); +typedef bool (*CryptoCtxReplayDictReader)(uint64_t* run_id, uint32_t* counter, void* context); + +size_t crypto_ctx_dump_replay_dict( + ESubGhzChatCryptoCtx* ctx, + CryptoCtxReplayDictWriter writer, + void* writer_ctx); +size_t crypto_ctx_read_replay_dict( + ESubGhzChatCryptoCtx* ctx, + CryptoCtxReplayDictReader reader, + void* reader_ctx); + #ifdef __cplusplus } #endif diff --git a/applications/external/esubghz_chat/esubghz_chat.c b/applications/external/esubghz_chat/esubghz_chat.c index 342f244ed..6a5778fd0 100644 --- a/applications/external/esubghz_chat/esubghz_chat.c +++ b/applications/external/esubghz_chat/esubghz_chat.c @@ -1,14 +1,13 @@ #include #include #include -#include +#include "helpers/radio_device_loader.h" #include "esubghz_chat_i.h" #define CHAT_LEAVE_DELAY 10 #define TICK_INTERVAL 50 #define MESSAGE_COMPLETION_TIMEOUT 500 -#define TIMEOUT_BETWEEN_MESSAGES 500 #define KBD_UNLOCK_CNT 3 #define KBD_UNLOCK_TIMEOUT 1000 @@ -125,15 +124,23 @@ void tx_msg_input(ESubGhzChatState* state) { subghz_tx_rx_worker_write(state->subghz_worker, state->tx_buffer, tx_size); } -/* Displays whether or not encryption has been enabled in the text box. Also - * clears the text input buffer to remove the password and starts the Sub-GHz - * worker. After starting the worker a join message is transmitted. */ +/* Displays information on frequency, encryption and radio type in the text + * box. Also clears the text input buffer to remove the password and starts the + * Sub-GHz worker. After starting the worker a join message is transmitted. */ void enter_chat(ESubGhzChatState* state) { + furi_string_cat_printf(state->chat_box_store, "Frequency: %lu", state->frequency); + furi_string_cat_printf( state->chat_box_store, "\nEncrypted: %s", (state->encrypted ? "yes" : "no")); subghz_tx_rx_worker_start(state->subghz_worker, state->subghz_device, state->frequency); + if(strcmp(state->subghz_device->name, "cc1101_ext") == 0) { + furi_string_cat_printf(state->chat_box_store, "\nRadio: External"); + } else { + furi_string_cat_printf(state->chat_box_store, "\nRadio: Internal"); + } + /* concatenate the name prefix and join message */ furi_string_set(state->msg_input, state->name_prefix); furi_string_cat_str(state->msg_input, " joined chat."); @@ -523,6 +530,9 @@ int32_t esubghz_chat(void) { goto err_alloc_crypto; } + /* set the default frequency */ + state->frequency = DEFAULT_FREQ; + /* set the have_read callback of the Sub-GHz worker */ subghz_tx_rx_worker_set_callback_have_read(state->subghz_worker, have_read_cb, state); @@ -531,7 +541,12 @@ int32_t esubghz_chat(void) { /* init internal device */ subghz_devices_init(); - state->subghz_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME); + + state->subghz_device = + radio_device_loader_set(state->subghz_device, SubGhzRadioDeviceTypeExternalCC1101); + + subghz_devices_reset(state->subghz_device); + subghz_devices_idle(state->subghz_device); /* set chat name prefix */ furi_string_printf(state->name_prefix, "%s", furi_hal_version_get_name_ptr()); @@ -582,8 +597,8 @@ int32_t esubghz_chat(void) { Gui* gui = furi_record_open(RECORD_GUI); view_dispatcher_attach_to_gui(state->view_dispatcher, gui, ViewDispatcherTypeFullscreen); - /* switch to the frequency input scene */ - scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_FreqInput); + /* switch to the key menu scene */ + scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_KeyMenu); /* run the view dispatcher, this call only returns when we close the * application */ @@ -627,6 +642,8 @@ int32_t esubghz_chat(void) { crypto_explicit_bzero(state->nfc_dev_data, sizeof(NfcDeviceData)); /* deinit devices */ + radio_device_loader_end(state->subghz_device); + subghz_devices_deinit(); /* exit suppress charge mode */ diff --git a/applications/external/esubghz_chat/esubghz_chat_i.h b/applications/external/esubghz_chat/esubghz_chat_i.h index b29e6292d..4c6458cec 100644 --- a/applications/external/esubghz_chat/esubghz_chat_i.h +++ b/applications/external/esubghz_chat/esubghz_chat_i.h @@ -18,8 +18,8 @@ #include "crypto_wrapper.h" #include "scenes/esubghz_chat_scene.h" -#include #include "esubghz_chat_icons.h" +#include #define APPLICATION_NAME "ESubGhzChat" diff --git a/applications/external/esubghz_chat/helpers/nfc_helpers.h b/applications/external/esubghz_chat/helpers/nfc_helpers.h new file mode 100644 index 000000000..5e507e335 --- /dev/null +++ b/applications/external/esubghz_chat/helpers/nfc_helpers.h @@ -0,0 +1,25 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#define NFC_MAX_BYTES 256 +#define NFC_CONFIG_PAGES 4 + +struct FreqNfcEntry { + uint32_t frequency; + uint32_t unused1; + uint32_t unused2; + uint32_t unused3; +} __attribute__((packed)); + +struct ReplayDictNfcEntry { + uint64_t run_id; + uint32_t counter; + uint32_t unused; +} __attribute__((packed)); + +#ifdef __cplusplus +} +#endif diff --git a/applications/external/esubghz_chat/helpers/radio_device_loader.c b/applications/external/esubghz_chat/helpers/radio_device_loader.c new file mode 100644 index 000000000..91f006a44 --- /dev/null +++ b/applications/external/esubghz_chat/helpers/radio_device_loader.c @@ -0,0 +1,65 @@ +#include "radio_device_loader.h" + +#include +#include + +static void radio_device_loader_power_on() { + uint8_t attempts = 0; + while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) { + furi_hal_power_enable_otg(); + //CC1101 power-up time + furi_delay_ms(10); + } +} + +static void radio_device_loader_power_off() { + if(furi_hal_power_is_otg_enabled()) furi_hal_power_disable_otg(); +} + +bool radio_device_loader_is_connect_external(const char* name) { + bool is_connect = false; + bool is_otg_enabled = furi_hal_power_is_otg_enabled(); + + if(!is_otg_enabled) { + radio_device_loader_power_on(); + } + + const SubGhzDevice* device = subghz_devices_get_by_name(name); + if(device) { + is_connect = subghz_devices_is_connect(device); + } + + if(!is_otg_enabled) { + radio_device_loader_power_off(); + } + return is_connect; +} + +const SubGhzDevice* radio_device_loader_set( + const SubGhzDevice* current_radio_device, + SubGhzRadioDeviceType radio_device_type) { + const SubGhzDevice* radio_device; + + if(radio_device_type == SubGhzRadioDeviceTypeExternalCC1101 && + radio_device_loader_is_connect_external(SUBGHZ_DEVICE_CC1101_EXT_NAME)) { + radio_device_loader_power_on(); + radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_EXT_NAME); + subghz_devices_begin(radio_device); + } else if(current_radio_device == NULL) { + radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME); + } else { + radio_device_loader_end(current_radio_device); + radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME); + } + + return radio_device; +} + +void radio_device_loader_end(const SubGhzDevice* radio_device) { + furi_assert(radio_device); + radio_device_loader_power_off(); + // Code below is not used (and will cause crash) since its called from tx_rx worker end! + //if(radio_device != subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME)) { + // subghz_devices_end(radio_device); + //} +} \ No newline at end of file diff --git a/applications/external/esubghz_chat/helpers/radio_device_loader.h b/applications/external/esubghz_chat/helpers/radio_device_loader.h new file mode 100644 index 000000000..bee4e2c36 --- /dev/null +++ b/applications/external/esubghz_chat/helpers/radio_device_loader.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +/** SubGhzRadioDeviceType */ +typedef enum { + SubGhzRadioDeviceTypeInternal, + SubGhzRadioDeviceTypeExternalCC1101, +} SubGhzRadioDeviceType; + +const SubGhzDevice* radio_device_loader_set( + const SubGhzDevice* current_radio_device, + SubGhzRadioDeviceType radio_device_type); + +void radio_device_loader_end(const SubGhzDevice* radio_device); \ No newline at end of file diff --git a/applications/external/esubghz_chat/scenes/esubghz_chat_freq_input.c b/applications/external/esubghz_chat/scenes/esubghz_chat_freq_input.c index ccce26418..3c74caec3 100644 --- a/applications/external/esubghz_chat/scenes/esubghz_chat_freq_input.c +++ b/applications/external/esubghz_chat/scenes/esubghz_chat_freq_input.c @@ -1,12 +1,11 @@ #include "../esubghz_chat_i.h" -/* Sends FreqEntered event to scene manager and displays the frequency in the - * text box. */ +/* Sends FreqEntered event to scene manager and enters the chat. */ static void freq_input_cb(void* context) { furi_assert(context); ESubGhzChatState* state = context; - furi_string_cat_printf(state->chat_box_store, "Frequency: %lu", state->frequency); + enter_chat(state); view_dispatcher_send_custom_event(state->view_dispatcher, ESubGhzChatEvent_FreqEntered); } @@ -49,7 +48,7 @@ void scene_on_enter_freq_input(void* context) { furi_assert(context); ESubGhzChatState* state = context; - snprintf(state->text_input_store, TEXT_INPUT_STORE_SIZE, "%lu", (uint32_t)DEFAULT_FREQ); + snprintf(state->text_input_store, TEXT_INPUT_STORE_SIZE, "%lu", state->frequency); text_input_reset(state->text_input); text_input_set_result_callback( state->text_input, @@ -76,9 +75,9 @@ bool scene_on_event_freq_input(void* context, SceneManagerEvent event) { switch(event.type) { case SceneManagerEventTypeCustom: switch(event.event) { - /* switch to password input scene */ + /* switch to message input scene */ case ESubGhzChatEvent_FreqEntered: - scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_KeyMenu); + scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_ChatInput); consumed = true; break; } diff --git a/applications/external/esubghz_chat/scenes/esubghz_chat_hex_key_input.c b/applications/external/esubghz_chat/scenes/esubghz_chat_hex_key_input.c index 564bfde8f..00d9e70f3 100644 --- a/applications/external/esubghz_chat/scenes/esubghz_chat_hex_key_input.c +++ b/applications/external/esubghz_chat/scenes/esubghz_chat_hex_key_input.c @@ -1,7 +1,7 @@ #include "../esubghz_chat_i.h" -/* Sets the entered bytes as the key, enters the chat and sends a HexKeyEntered - * event to the scene manager. */ +/* Sets the entered bytes as the key and sends a HexKeyEntered event to the + * scene manager. */ static void hex_key_input_cb(void* context) { furi_assert(context); ESubGhzChatState* state = context; @@ -20,8 +20,6 @@ static void hex_key_input_cb(void* context) { state->encrypted = true; - enter_chat(state); - view_dispatcher_send_custom_event(state->view_dispatcher, ESubGhzChatEvent_HexKeyEntered); } @@ -55,9 +53,9 @@ bool scene_on_event_hex_key_input(void* context, SceneManagerEvent event) { switch(event.type) { case SceneManagerEventTypeCustom: switch(event.event) { - /* switch to message input scene */ + /* switch to frequency input scene */ case ESubGhzChatEvent_HexKeyEntered: - scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_ChatInput); + scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_FreqInput); consumed = true; break; } diff --git a/applications/external/esubghz_chat/scenes/esubghz_chat_key_menu.c b/applications/external/esubghz_chat/scenes/esubghz_chat_key_menu.c index 13483bf53..cd1269ee1 100644 --- a/applications/external/esubghz_chat/scenes/esubghz_chat_key_menu.c +++ b/applications/external/esubghz_chat/scenes/esubghz_chat_key_menu.c @@ -17,7 +17,6 @@ static void key_menu_cb(void* context, uint32_t index) { switch(index) { case ESubGhzChatKeyMenuItems_NoEncryption: state->encrypted = false; - enter_chat(state); view_dispatcher_send_custom_event( state->view_dispatcher, ESubGhzChatEvent_KeyMenuNoEncryption); @@ -49,7 +48,6 @@ static void key_menu_cb(void* context, uint32_t index) { /* set encrypted flag and enter the chat */ state->encrypted = true; - enter_chat(state); view_dispatcher_send_custom_event(state->view_dispatcher, ESubGhzChatEvent_KeyMenuGenKey); break; @@ -73,33 +71,37 @@ void scene_on_enter_key_menu(void* context) { menu_reset(state->menu); + /* clear the crypto CTX in case we got back from password or hex key + * input */ + crypto_ctx_clear(state->crypto_ctx); + menu_add_item( state->menu, "No encryption", - &I_chat_10px, + &I_chat_14px, ESubGhzChatKeyMenuItems_NoEncryption, key_menu_cb, state); menu_add_item( state->menu, "Password", - &I_keyboard_10px, + &I_keyboard_14px, ESubGhzChatKeyMenuItems_Password, key_menu_cb, state); menu_add_item( - state->menu, "Hex Key", &I_hex_10px, ESubGhzChatKeyMenuItems_HexKey, key_menu_cb, state); + state->menu, "Hex Key", &I_hex_14px, ESubGhzChatKeyMenuItems_HexKey, key_menu_cb, state); menu_add_item( state->menu, "Generate Key", - &I_u2f_10px, + &I_u2f_14px, ESubGhzChatKeyMenuItems_GenKey, key_menu_cb, state); menu_add_item( state->menu, "Read Key from NFC", - &I_Nfc_10px, + &I_Nfc_14px, ESubGhzChatKeyMenuItems_ReadKeyFromNfc, key_menu_cb, state); @@ -119,10 +121,10 @@ bool scene_on_event_key_menu(void* context, SceneManagerEvent event) { switch(event.type) { case SceneManagerEventTypeCustom: switch(event.event) { - /* switch to message input scene */ + /* switch to frequency input scene */ case ESubGhzChatEvent_KeyMenuNoEncryption: case ESubGhzChatEvent_KeyMenuGenKey: - scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_ChatInput); + scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_FreqInput); consumed = true; break; diff --git a/applications/external/esubghz_chat/scenes/esubghz_chat_key_read_popup.c b/applications/external/esubghz_chat/scenes/esubghz_chat_key_read_popup.c index 4d5904406..db1f75491 100644 --- a/applications/external/esubghz_chat/scenes/esubghz_chat_key_read_popup.c +++ b/applications/external/esubghz_chat/scenes/esubghz_chat_key_read_popup.c @@ -1,4 +1,5 @@ #include "../esubghz_chat_i.h" +#include "../helpers/nfc_helpers.h" typedef enum { KeyReadPopupState_Idle, @@ -28,18 +29,46 @@ static void key_read_popup_timeout_cb(void* context) { if(cur_state == KeyReadPopupState_Fail) { view_dispatcher_send_custom_event( state->view_dispatcher, ESubGhzChatEvent_KeyReadPopupFailed); - /* done displaying our success, enter chat */ + /* done displaying our success */ } else if(cur_state == KeyReadPopupState_Success) { - enter_chat(state); view_dispatcher_send_custom_event( state->view_dispatcher, ESubGhzChatEvent_KeyReadPopupSucceeded); } } +struct ReplayDictNfcReaderContext { + uint8_t* cur; + uint8_t* max; +}; + +static bool replay_dict_nfc_reader(uint64_t* run_id, uint32_t* counter, void* context) { + struct ReplayDictNfcReaderContext* ctx = (struct ReplayDictNfcReaderContext*)context; + + if(ctx->cur + sizeof(struct ReplayDictNfcEntry) > ctx->max) { + return false; + } + + struct ReplayDictNfcEntry* entry = (struct ReplayDictNfcEntry*)ctx->cur; + *run_id = entry->run_id; + *counter = __ntohl(entry->counter); + + ctx->cur += sizeof(struct ReplayDictNfcEntry); + + return true; +} + static bool key_read_popup_handle_key_read(ESubGhzChatState* state) { NfcDeviceData* dev_data = state->nfc_dev_data; - if(dev_data->mf_ul_data.data_read < KEY_BITS / 8) { + /* check for config pages */ + if(dev_data->mf_ul_data.data_read < NFC_CONFIG_PAGES * 4) { + return false; + } + + size_t data_read = dev_data->mf_ul_data.data_read - (NFC_CONFIG_PAGES * 4); + + /* check if key was transmitted */ + if(data_read < KEY_BITS / 8) { return false; } @@ -55,6 +84,21 @@ static bool key_read_popup_handle_key_read(ESubGhzChatState* state) { return false; } + /* read the frequency */ + if(data_read >= (KEY_BITS / 8) + sizeof(struct FreqNfcEntry)) { + struct FreqNfcEntry* freq_entry = + (struct FreqNfcEntry*)(dev_data->mf_ul_data.data + (KEY_BITS / 8)); + state->frequency = __ntohl(freq_entry->frequency); + } + + /* read the replay dict */ + struct ReplayDictNfcReaderContext rd_ctx = { + .cur = dev_data->mf_ul_data.data + (KEY_BITS / 8) + sizeof(struct FreqNfcEntry), + .max = + dev_data->mf_ul_data.data + (data_read < NFC_MAX_BYTES ? data_read : NFC_MAX_BYTES)}; + + crypto_ctx_read_replay_dict(state->crypto_ctx, replay_dict_nfc_reader, &rd_ctx); + /* set encrypted flag */ state->encrypted = true; @@ -183,9 +227,9 @@ bool scene_on_event_key_read_popup(void* context, SceneManagerEvent event) { consumed = true; break; - /* success, go to chat input */ + /* success, go to frequency input */ case ESubGhzChatEvent_KeyReadPopupSucceeded: - scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_ChatInput); + scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_FreqInput); consumed = true; break; diff --git a/applications/external/esubghz_chat/scenes/esubghz_chat_key_share_popup.c b/applications/external/esubghz_chat/scenes/esubghz_chat_key_share_popup.c index a3230049c..07d85cb33 100644 --- a/applications/external/esubghz_chat/scenes/esubghz_chat_key_share_popup.c +++ b/applications/external/esubghz_chat/scenes/esubghz_chat_key_share_popup.c @@ -1,4 +1,25 @@ #include "../esubghz_chat_i.h" +#include "../helpers/nfc_helpers.h" + +struct ReplayDictNfcWriterContext { + uint8_t* cur; + uint8_t* max; +}; + +static bool replay_dict_nfc_writer(uint64_t run_id, uint32_t counter, void* context) { + struct ReplayDictNfcWriterContext* ctx = (struct ReplayDictNfcWriterContext*)context; + + struct ReplayDictNfcEntry entry = {.run_id = run_id, .counter = __htonl(counter), .unused = 0}; + + if(ctx->cur + sizeof(entry) > ctx->max) { + return false; + } + + memcpy(ctx->cur, &entry, sizeof(entry)); + ctx->cur += sizeof(entry); + + return true; +} static void prepare_nfc_dev_data(ESubGhzChatState* state) { NfcDeviceData* dev_data = state->nfc_dev_data; @@ -20,9 +41,32 @@ static void prepare_nfc_dev_data(ESubGhzChatState* state) { dev_data->mf_ul_data.version.storage_size = 0x11; dev_data->mf_ul_data.version.protocol_type = 0x03; - /* Add 16 to the size for config pages */ - dev_data->mf_ul_data.data_size = (KEY_BITS / 8) + 16; + size_t data_written = 0; + + /* write key */ crypto_ctx_get_key(state->crypto_ctx, dev_data->mf_ul_data.data); + data_written += (KEY_BITS / 8); + + /* write frequency */ + struct FreqNfcEntry* freq_entry = + (struct FreqNfcEntry*)(dev_data->mf_ul_data.data + data_written); + freq_entry->frequency = __htonl(state->frequency); + freq_entry->unused1 = 0; + freq_entry->unused2 = 0; + freq_entry->unused3 = 0; + data_written += sizeof(struct FreqNfcEntry); + + /* write the replay dict */ + struct ReplayDictNfcWriterContext wr_ctx = { + .cur = dev_data->mf_ul_data.data + data_written, + .max = dev_data->mf_ul_data.data + NFC_MAX_BYTES}; + + size_t n_entries = + crypto_ctx_dump_replay_dict(state->crypto_ctx, replay_dict_nfc_writer, &wr_ctx); + data_written += n_entries * sizeof(struct ReplayDictNfcEntry); + + /* calculate size of data, add 16 for config pages */ + dev_data->mf_ul_data.data_size = data_written + (NFC_CONFIG_PAGES * 4); } /* Prepares the key share popup scene. */ diff --git a/applications/external/esubghz_chat/scenes/esubghz_chat_pass_input.c b/applications/external/esubghz_chat/scenes/esubghz_chat_pass_input.c index cb40fc7fd..f1cf4bfa7 100644 --- a/applications/external/esubghz_chat/scenes/esubghz_chat_pass_input.c +++ b/applications/external/esubghz_chat/scenes/esubghz_chat_pass_input.c @@ -1,14 +1,12 @@ #include "../esubghz_chat_i.h" -/* Sends PassEntered event to scene manager and enters the chat. */ +/* Sends PassEntered event to scene manager. */ static void pass_input_cb(void* context) { furi_assert(context); ESubGhzChatState* state = context; crypto_explicit_bzero(state->text_input_store, sizeof(state->text_input_store)); - enter_chat(state); - view_dispatcher_send_custom_event(state->view_dispatcher, ESubGhzChatEvent_PassEntered); } @@ -83,9 +81,9 @@ bool scene_on_event_pass_input(void* context, SceneManagerEvent event) { switch(event.type) { case SceneManagerEventTypeCustom: switch(event.event) { - /* switch to message input scene */ + /* switch to frequency input scene */ case ESubGhzChatEvent_PassEntered: - scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_ChatInput); + scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_FreqInput); consumed = true; break; } diff --git a/applications/external/etch_a_sketch/application.fam b/applications/external/etch_a_sketch/application.fam index db1add1ab..2f6cd9136 100644 --- a/applications/external/etch_a_sketch/application.fam +++ b/applications/external/etch_a_sketch/application.fam @@ -6,7 +6,6 @@ App( cdefines=["APP_ETCH_A_SKETCH"], requires=["gui"], stack_size=2 * 1024, - order=175, fap_icon="etch-a-sketch-icon.png", fap_category="Media", fap_icon_assets="assets", diff --git a/applications/external/evil_portal/LICENSE.txt b/applications/external/evil_portal/LICENSE.txt new file mode 100644 index 000000000..2ae63a7f6 --- /dev/null +++ b/applications/external/evil_portal/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 bigbrodude6119 + +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/evil_portal/application.fam b/applications/external/evil_portal/application.fam index 58c7d426c..6af0546c4 100644 --- a/applications/external/evil_portal/application.fam +++ b/applications/external/evil_portal/application.fam @@ -6,7 +6,9 @@ App( cdefines=["APP_EVIL_PORTAL"], requires=["gui"], stack_size=1 * 1024, - order=90, + fap_author="bigbrodude6119", + fap_description="Create an evil captive portal Wi-Fi access point", + fap_icon_assets="icons", fap_icon="icons/evil_portal_10px.png", fap_category="WiFi", ) diff --git a/applications/external/evil_portal/evil_portal_app.c b/applications/external/evil_portal/evil_portal_app.c index ef3131f46..8e091da40 100644 --- a/applications/external/evil_portal/evil_portal_app.c +++ b/applications/external/evil_portal/evil_portal_app.c @@ -32,10 +32,15 @@ Evil_PortalApp* evil_portal_app_alloc() { app->command_index = 0; app->portal_logs = furi_string_alloc(); - app->gui = furi_record_open(RECORD_GUI); app->dialogs = furi_record_open(RECORD_DIALOGS); + app->file_path = furi_string_alloc(); + + app->gui = furi_record_open(RECORD_GUI); app->view_dispatcher = view_dispatcher_alloc(); + + app->loading = loading_alloc(); + app->scene_manager = scene_manager_alloc(&evil_portal_scene_handlers, app); view_dispatcher_enable_queue(app->view_dispatcher); view_dispatcher_set_event_callback_context(app->view_dispatcher, app); @@ -49,12 +54,18 @@ Evil_PortalApp* evil_portal_app_alloc() { view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + app->view_stack = view_stack_alloc(); + app->var_item_list = variable_item_list_alloc(); view_dispatcher_add_view( app->view_dispatcher, Evil_PortalAppViewVarItemList, variable_item_list_get_view(app->var_item_list)); + app->text_input = text_input_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, Evil_PortalAppViewTextInput, text_input_get_view(app->text_input)); + for(int i = 0; i < NUM_MENU_ITEMS; ++i) { app->selected_option_index[i] = 0; } @@ -89,6 +100,10 @@ void evil_portal_app_free(Evil_PortalApp* app) { text_box_free(app->text_box); furi_string_free(app->text_box_store); + text_input_free(app->text_input); + + view_stack_free(app->view_stack); + loading_free(app->loading); // View dispatcher view_dispatcher_free(app->view_dispatcher); @@ -98,36 +113,32 @@ void evil_portal_app_free(Evil_PortalApp* app) { // Close records furi_record_close(RECORD_GUI); + furi_record_close(RECORD_DIALOGS); + furi_string_free(app->file_path); free(app); } int32_t evil_portal_app(void* p) { UNUSED(p); + Evil_PortalApp* evil_portal_app = evil_portal_app_alloc(); - // turn off 5v, so it gets reset on startup - if(furi_hal_power_is_otg_enabled()) { - furi_hal_power_disable_otg(); - } - - // Enable 5v on startup uint8_t attempts = 0; + bool otg_was_enabled = furi_hal_power_is_otg_enabled(); while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) { furi_hal_power_enable_otg(); furi_delay_ms(10); } furi_delay_ms(200); - Evil_PortalApp* evil_portal_app = evil_portal_app_alloc(); - evil_portal_app->uart = evil_portal_uart_init(evil_portal_app); view_dispatcher_run(evil_portal_app->view_dispatcher); evil_portal_app_free(evil_portal_app); - if(furi_hal_power_is_otg_enabled()) { + if(furi_hal_power_is_otg_enabled() && !otg_was_enabled) { furi_hal_power_disable_otg(); } diff --git a/applications/external/evil_portal/evil_portal_app.h b/applications/external/evil_portal/evil_portal_app.h index 65c047ea5..bb663ec22 100644 --- a/applications/external/evil_portal/evil_portal_app.h +++ b/applications/external/evil_portal/evil_portal_app.h @@ -8,4 +8,4 @@ typedef struct Evil_PortalApp Evil_PortalApp; #ifdef __cplusplus } -#endif +#endif \ No newline at end of file diff --git a/applications/external/evil_portal/evil_portal_app_i.h b/applications/external/evil_portal/evil_portal_app_i.h index af36d8eb9..bbe82cbd8 100644 --- a/applications/external/evil_portal/evil_portal_app_i.h +++ b/applications/external/evil_portal/evil_portal_app_i.h @@ -4,19 +4,22 @@ #include "evil_portal_custom_event.h" #include "evil_portal_uart.h" #include "scenes/evil_portal_scene.h" +#include "evil_portal_icons.h" +#include #include +#include #include +#include #include #include #include - -#include +#include #include #include -#define NUM_MENU_ITEMS (4) +#define NUM_MENU_ITEMS (6) #define EVIL_PORTAL_TEXT_BOX_STORE_SIZE (4096) #define UART_CH \ @@ -27,14 +30,13 @@ #define SET_AP_CMD "setap" #define RESET_CMD "reset" -#define EVIL_PORTAL_INDEX_EXTENSION ".html" -#define EVIL_PORTAL_BASE_FOLDER STORAGE_APP_DATA_PATH_PREFIX +#define HTML_EXTENSION ".html" +#define HTML_FOLDER APP_DATA_PATH("html") struct Evil_PortalApp { Gui* gui; ViewDispatcher* view_dispatcher; SceneManager* scene_manager; - DialogsApp* dialogs; FuriString* portal_logs; const char* command_queue[1]; @@ -47,6 +49,11 @@ struct Evil_PortalApp { VariableItemList* var_item_list; Evil_PortalUart* uart; + TextInput* text_input; + DialogsApp* dialogs; + FuriString* file_path; + Loading* loading; + ViewStack* view_stack; int selected_menu_index; int selected_option_index[NUM_MENU_ITEMS]; @@ -59,6 +66,7 @@ struct Evil_PortalApp { bool sent_html; bool sent_reset; int BAUDRATE; + char text_store[2][128 + 1]; uint8_t* index_html; uint8_t* ap_name; @@ -68,4 +76,5 @@ typedef enum { Evil_PortalAppViewVarItemList, Evil_PortalAppViewConsoleOutput, Evil_PortalAppViewStartPortal, + Evil_PortalAppViewTextInput, } Evil_PortalAppView; diff --git a/applications/external/evil_portal/evil_portal_custom_event.h b/applications/external/evil_portal/evil_portal_custom_event.h index a566ca62e..a4609e00a 100644 --- a/applications/external/evil_portal/evil_portal_custom_event.h +++ b/applications/external/evil_portal/evil_portal_custom_event.h @@ -5,4 +5,5 @@ typedef enum { Evil_PortalEventStartConsole, Evil_PortalEventStartKeyboard, Evil_PortalEventStartPortal, + Evil_PortalEventTextInput, } Evil_PortalCustomEvent; diff --git a/applications/external/evil_portal/helpers/evil_portal_storage.c b/applications/external/evil_portal/helpers/evil_portal_storage.c index aa9a50493..22dd11dfb 100644 --- a/applications/external/evil_portal/helpers/evil_portal_storage.c +++ b/applications/external/evil_portal/helpers/evil_portal_storage.c @@ -8,31 +8,21 @@ static void evil_portal_close_storage() { furi_record_close(RECORD_STORAGE); } -bool evil_portal_read_index_html(void* context) { - FuriString* file_path = furi_string_alloc_set(EVIL_PORTAL_BASE_FOLDER); - - DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options( - &browser_options, - EVIL_PORTAL_INDEX_EXTENSION, - NULL); // TODO configure icon - browser_options.base_path = EVIL_PORTAL_BASE_FOLDER; - +void evil_portal_read_index_html(void* context) { Evil_PortalApp* app = context; - bool res = dialog_file_browser_show(app->dialogs, file_path, file_path, &browser_options); - - if(!res) { - furi_string_free(file_path); - return false; - } - Storage* storage = evil_portal_open_storage(); FileInfo fi; - if(storage_common_stat(storage, furi_string_get_cstr(file_path), &fi) == FSE_OK) { + if(!storage_common_exists(storage, EVIL_PORTAL_INDEX_SAVE_PATH)) { + FuriString* tmp = furi_string_alloc_set(EVIL_PORTAL_INDEX_DEFAULT_PATH); + evil_portal_replace_index_html(tmp); + furi_string_free(tmp); + } + + if(storage_common_stat(storage, EVIL_PORTAL_INDEX_SAVE_PATH, &fi) == FSE_OK) { File* index_html = storage_file_alloc(storage); if(storage_file_open( - index_html, furi_string_get_cstr(file_path), FSAM_READ, FSOM_OPEN_EXISTING)) { + index_html, EVIL_PORTAL_INDEX_SAVE_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) { app->index_html = malloc((size_t)fi.size); uint8_t* buf_ptr = app->index_html; size_t read = 0; @@ -45,7 +35,6 @@ bool evil_portal_read_index_html(void* context) { } free(buf_ptr); } - furi_string_free(file_path); storage_file_close(index_html); storage_file_free(index_html); } else { @@ -57,7 +46,33 @@ bool evil_portal_read_index_html(void* context) { } evil_portal_close_storage(); - return true; +} + +void evil_portal_replace_index_html(FuriString* path) { + Storage* storage = evil_portal_open_storage(); + FS_Error error; + error = storage_common_remove(storage, EVIL_PORTAL_INDEX_SAVE_PATH); + if(error != FSE_OK) { + FURI_LOG_D("EVIL PORTAL", "Error removing file"); + } else { + FURI_LOG_D("EVIL PORTAL", "Error removed file"); + } + error = storage_common_copy(storage, furi_string_get_cstr(path), EVIL_PORTAL_INDEX_SAVE_PATH); + if(error != FSE_OK) { + FURI_LOG_D("EVIL PORTAL", "Error copying file"); + } + evil_portal_close_storage(); +} + +void evil_portal_create_html_folder_if_not_exists() { + Storage* storage = evil_portal_open_storage(); + if(storage_common_stat(storage, HTML_FOLDER, NULL) == FSE_NOT_EXIST) { + FURI_LOG_D("Evil Portal", "Directory %s doesn't exist. Will create new.", HTML_FOLDER); + if(!storage_simply_mkdir(storage, HTML_FOLDER)) { + FURI_LOG_E("Evil Portal", "Error creating directory %s", HTML_FOLDER); + } + } + evil_portal_close_storage(); } void evil_portal_read_ap_name(void* context) { @@ -89,6 +104,19 @@ void evil_portal_read_ap_name(void* context) { evil_portal_close_storage(); } +void evil_portal_write_ap_name(void* context) { + Evil_PortalApp* app = context; + Storage* storage = evil_portal_open_storage(); + + File* ap_name = storage_file_alloc(storage); + if(storage_file_open(ap_name, EVIL_PORTAL_AP_SAVE_PATH, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { + storage_file_write(ap_name, app->text_store[0], strlen(app->text_store[0])); + } + storage_file_close(ap_name); + storage_file_free(ap_name); + evil_portal_close_storage(); +} + char* sequential_file_resolve_path( Storage* storage, const char* dir, diff --git a/applications/external/evil_portal/helpers/evil_portal_storage.h b/applications/external/evil_portal/helpers/evil_portal_storage.h index d4ad33e1d..ad0b8a392 100644 --- a/applications/external/evil_portal/helpers/evil_portal_storage.h +++ b/applications/external/evil_portal/helpers/evil_portal_storage.h @@ -1,5 +1,4 @@ #include "../evil_portal_app_i.h" -#include #include #include #include @@ -8,11 +7,15 @@ #define PORTAL_FILE_DIRECTORY_PATH EXT_PATH("apps_data/evil_portal") #define EVIL_PORTAL_INDEX_SAVE_PATH PORTAL_FILE_DIRECTORY_PATH "/index.html" +#define EVIL_PORTAL_INDEX_DEFAULT_PATH PORTAL_FILE_DIRECTORY_PATH "/html/xtreme.html" #define EVIL_PORTAL_AP_SAVE_PATH PORTAL_FILE_DIRECTORY_PATH "/ap.config.txt" #define EVIL_PORTAL_LOG_SAVE_PATH PORTAL_FILE_DIRECTORY_PATH "/logs" -bool evil_portal_read_index_html(void* context); +void evil_portal_read_index_html(void* context); void evil_portal_read_ap_name(void* context); +void evil_portal_write_ap_name(void* context); +void evil_portal_replace_index_html(FuriString* path); +void evil_portal_create_html_folder_if_not_exists(); void write_logs(FuriString* portal_logs); char* sequential_file_resolve_path( Storage* storage, diff --git a/applications/external/evil_portal/scenes/evil_portal_scene_config.h b/applications/external/evil_portal/scenes/evil_portal_scene_config.h index 94b09ae46..ffb958487 100644 --- a/applications/external/evil_portal/scenes/evil_portal_scene_config.h +++ b/applications/external/evil_portal/scenes/evil_portal_scene_config.h @@ -1,2 +1,4 @@ ADD_SCENE(evil_portal, start, Start) ADD_SCENE(evil_portal, console_output, ConsoleOutput) +ADD_SCENE(evil_portal, rename, Rename) +ADD_SCENE(evil_portal, select_html, SelectHtml) diff --git a/applications/external/evil_portal/scenes/evil_portal_scene_console_output.c b/applications/external/evil_portal/scenes/evil_portal_scene_console_output.c index 94f2cef4f..19b076845 100644 --- a/applications/external/evil_portal/scenes/evil_portal_scene_console_output.c +++ b/applications/external/evil_portal/scenes/evil_portal_scene_console_output.c @@ -22,8 +22,6 @@ void evil_portal_console_output_handle_rx_data_cb(uint8_t* buf, size_t len, void void evil_portal_scene_console_output_on_enter(void* context) { Evil_PortalApp* app = context; - bool portal_file_set = false; - TextBox* text_box = app->text_box; text_box_reset(app->text_box); text_box_set_font(text_box, TextBoxFontText); @@ -64,25 +62,24 @@ void evil_portal_scene_console_output_on_enter(void* context) { } } - if(0 == strncmp(SET_HTML_CMD, app->selected_tx_string, strlen(SET_HTML_CMD))) { - portal_file_set = evil_portal_read_index_html(context); + if(0 == strncmp("setapname", app->selected_tx_string, strlen("setapname"))) { + scene_manager_next_scene(app->scene_manager, Evil_PortalSceneRename); + return; + } - if(portal_file_set) { - app->command_queue[0] = SET_AP_CMD; - app->has_command_queue = true; - app->command_index = 0; - if(app->show_stopscan_tip) { - const char* msg = "Starting portal\nIf no response press\nBACK to return\n"; - furi_string_cat_str(app->text_box_store, msg); - app->text_box_store_strlen += strlen(msg); - } - } else { - if(app->show_stopscan_tip) { - const char* msg = "No portal selected\nShowing current logs\nPress " - "BACK to return\n"; - furi_string_cat_str(app->text_box_store, msg); - app->text_box_store_strlen += strlen(msg); - } + if(0 == strncmp("selecthtml", app->selected_tx_string, strlen("selecthtml"))) { + scene_manager_next_scene(app->scene_manager, Evil_PortalSceneSelectHtml); + return; + } + + if(0 == strncmp(SET_HTML_CMD, app->selected_tx_string, strlen(SET_HTML_CMD))) { + app->command_queue[0] = SET_AP_CMD; + app->has_command_queue = true; + app->command_index = 0; + if(app->show_stopscan_tip) { + const char* msg = "Starting portal\nIf no response press\nBACK to return\n"; + furi_string_cat_str(app->text_box_store, msg); + app->text_box_store_strlen += strlen(msg); } } @@ -107,13 +104,7 @@ void evil_portal_scene_console_output_on_enter(void* context) { if(app->is_command && app->selected_tx_string) { if(0 == strncmp(SET_HTML_CMD, app->selected_tx_string, strlen(SET_HTML_CMD))) { - if(!portal_file_set) { - scene_manager_set_scene_state( - app->scene_manager, Evil_PortalSceneConsoleOutput, 0); - view_dispatcher_switch_to_view( - app->view_dispatcher, Evil_PortalAppViewConsoleOutput); - return; - } + evil_portal_read_index_html(context); FuriString* data = furi_string_alloc(); furi_string_cat(data, "sethtml="); diff --git a/applications/external/evil_portal/scenes/evil_portal_scene_rename.c b/applications/external/evil_portal/scenes/evil_portal_scene_rename.c new file mode 100644 index 000000000..72f3ef18c --- /dev/null +++ b/applications/external/evil_portal/scenes/evil_portal_scene_rename.c @@ -0,0 +1,42 @@ +#include "../evil_portal_app_i.h" +#include "../helpers/evil_portal_storage.h" + +void evil_portal_text_input_callback(void* context) { + furi_assert(context); + Evil_PortalApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, Evil_PortalEventTextInput); +} + +void evil_portal_scene_rename_on_enter(void* context) { + Evil_PortalApp* app = context; + TextInput* text_input = app->text_input; + size_t enter_name_length = 25; + evil_portal_read_ap_name(app); + text_input_set_header_text(text_input, "AP Name/SSID"); + strncpy(app->text_store[0], (char*)app->ap_name, enter_name_length); + text_input_set_result_callback( + text_input, + evil_portal_text_input_callback, + context, + app->text_store[0], + enter_name_length, + false); + view_dispatcher_switch_to_view(app->view_dispatcher, Evil_PortalAppViewTextInput); +} + +bool evil_portal_scene_rename_on_event(void* context, SceneManagerEvent event) { + Evil_PortalApp* app = context; + SceneManager* scene_manager = app->scene_manager; + bool consumed = false; + if(event.type == SceneManagerEventTypeCustom) { + evil_portal_write_ap_name(app); + scene_manager_search_and_switch_to_previous_scene(scene_manager, Evil_PortalSceneStart); + consumed = true; + } + return consumed; +} + +void evil_portal_scene_rename_on_exit(void* context) { + Evil_PortalApp* app = context; + variable_item_list_reset(app->var_item_list); +} diff --git a/applications/external/evil_portal/scenes/evil_portal_scene_select_html.c b/applications/external/evil_portal/scenes/evil_portal_scene_select_html.c new file mode 100644 index 000000000..1dbcdd54d --- /dev/null +++ b/applications/external/evil_portal/scenes/evil_portal_scene_select_html.c @@ -0,0 +1,54 @@ +#include "../evil_portal_app_i.h" +#include "../helpers/evil_portal_storage.h" + +void evil_portal_show_loading_popup(Evil_PortalApp* app, bool show) { + TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME); + ViewStack* view_stack = app->view_stack; + Loading* loading = app->loading; + if(show) { + // Raise timer priority so that animations can play + vTaskPrioritySet(timer_task, configMAX_PRIORITIES - 1); + view_stack_add_view(view_stack, loading_get_view(loading)); + } else { + view_stack_remove_view(view_stack, loading_get_view(loading)); + // Restore default timer priority + vTaskPrioritySet(timer_task, configTIMER_TASK_PRIORITY); + } +} + +void evil_portal_scene_select_html_on_enter(void* context) { + Evil_PortalApp* app = context; + DialogsFileBrowserOptions browser_options; + evil_portal_create_html_folder_if_not_exists(); + + dialog_file_browser_set_basic_options(&browser_options, HTML_EXTENSION, &I_evil_portal_10px); + browser_options.base_path = HTML_FOLDER; + + FuriString* path; + path = furi_string_alloc(); + + furi_string_set(path, HTML_FOLDER); + + bool success = dialog_file_browser_show(app->dialogs, app->file_path, path, &browser_options); + furi_string_free(path); + + if(success) { + //Replace HTML File + evil_portal_show_loading_popup(app, true); + evil_portal_replace_index_html(app->file_path); + evil_portal_show_loading_popup(app, false); + } + + scene_manager_search_and_switch_to_previous_scene(app->scene_manager, Evil_PortalSceneStart); +} + +bool evil_portal_scene_select_html_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); + bool consumed = true; + return consumed; +} + +void evil_portal_scene_select_html_on_exit(void* context) { + UNUSED(context); +} diff --git a/applications/external/evil_portal/scenes/evil_portal_scene_start.c b/applications/external/evil_portal/scenes/evil_portal_scene_start.c index 7f7200fcb..b06aedc51 100644 --- a/applications/external/evil_portal/scenes/evil_portal_scene_start.c +++ b/applications/external/evil_portal/scenes/evil_portal_scene_start.c @@ -33,6 +33,12 @@ const Evil_PortalItem items[NUM_MENU_ITEMS] = { // console {"Save logs", {""}, 1, {"savelogs"}, NO_ARGS, FOCUS_CONSOLE_START, SHOW_STOPSCAN_TIP}, + // set AP name + {"Set AP name", {""}, 1, {"setapname"}, NO_ARGS, FOCUS_CONSOLE_START, SHOW_STOPSCAN_TIP}, + + // select HTML Portal File + {"Select HTML", {""}, 1, {"selecthtml"}, NO_ARGS, FOCUS_CONSOLE_START, SHOW_STOPSCAN_TIP}, + // help {"Help", {""}, 1, {"help"}, NO_ARGS, FOCUS_CONSOLE_START, SHOW_STOPSCAN_TIP}, }; diff --git a/applications/external/flappy_bird/application.fam b/applications/external/flappy_bird/application.fam index ad18e57e1..625c5f66c 100644 --- a/applications/external/flappy_bird/application.fam +++ b/applications/external/flappy_bird/application.fam @@ -5,7 +5,6 @@ App( entry_point="flappy_game_app", requires=["gui"], stack_size=4 * 1024, - order=100, fap_icon="flappy_10px.png", fap_category="Games", fap_icon_assets="assets", diff --git a/applications/external/flappy_bird/flappy_bird.c b/applications/external/flappy_bird/flappy_bird.c index 3100b7c6b..496ffcf56 100644 --- a/applications/external/flappy_bird/flappy_bird.c +++ b/applications/external/flappy_bird/flappy_bird.c @@ -1,9 +1,11 @@ #include -#include +#include "flappy_bird_icons.h" +#include #include #include #include +#include #define TAG "Flappy" #define DEBUG false @@ -311,6 +313,9 @@ int32_t flappy_game_app(void* p) { Gui* gui = furi_record_open(RECORD_GUI); gui_add_view_port(gui, view_port, GuiLayerFullscreen); + // Call dolphin deed on game start + dolphin_deed(DolphinDeedPluginGameStart); + GameEvent event; for(bool processing = true; processing;) { FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); diff --git a/applications/external/flashlight/application.fam b/applications/external/flashlight/application.fam index a71258013..4ad9b6101 100644 --- a/applications/external/flashlight/application.fam +++ b/applications/external/flashlight/application.fam @@ -8,7 +8,6 @@ App( "gui", ], stack_size=2 * 1024, - order=20, fap_icon="flash10px.png", fap_category="GPIO", fap_author="@xMasterX", diff --git a/applications/external/flipbip/application.fam b/applications/external/flipbip/application.fam index bae1c0fb6..0831ff432 100644 --- a/applications/external/flipbip/application.fam +++ b/applications/external/flipbip/application.fam @@ -7,7 +7,6 @@ App( "gui", ], stack_size=3 * 1024, - order=10, fap_icon="flipbip_10px.png", fap_private_libs=[ Lib( diff --git a/applications/external/flipbip/icons/ButtonDown_10x5.png b/applications/external/flipbip/icons/ButtonDown_10x5.png new file mode 100644 index 000000000..b492b926c Binary files /dev/null and b/applications/external/flipbip/icons/ButtonDown_10x5.png differ diff --git a/applications/external/flipbip/icons/ButtonUp_10x5.png b/applications/external/flipbip/icons/ButtonUp_10x5.png new file mode 100644 index 000000000..5da99d01e Binary files /dev/null and b/applications/external/flipbip/icons/ButtonUp_10x5.png differ diff --git a/applications/external/flipper_i2ctools/application.fam b/applications/external/flipper_i2ctools/application.fam index 128f609a1..5ed100750 100644 --- a/applications/external/flipper_i2ctools/application.fam +++ b/applications/external/flipper_i2ctools/application.fam @@ -5,7 +5,6 @@ App( entry_point="i2ctools_app", requires=["gui"], stack_size=2 * 1024, - order=175, fap_icon="i2ctools.png", fap_category="GPIO", fap_icon_assets="images", diff --git a/applications/external/flipper_i2ctools/images/Voltage_16x16.png b/applications/external/flipper_i2ctools/images/Voltage_16x16.png deleted file mode 100644 index 94e796872..000000000 Binary files a/applications/external/flipper_i2ctools/images/Voltage_16x16.png and /dev/null differ diff --git a/applications/external/flipper_i2ctools/views/infos_view.h b/applications/external/flipper_i2ctools/views/infos_view.h index 11b388c02..db7330483 100644 --- a/applications/external/flipper_i2ctools/views/infos_view.h +++ b/applications/external/flipper_i2ctools/views/infos_view.h @@ -1,7 +1,8 @@ #include #include #include -#include +#include "i2ctools_icons.h" +#include #define INFOS_TEXT "INFOS" diff --git a/applications/external/flipper_i2ctools/views/main_view.h b/applications/external/flipper_i2ctools/views/main_view.h index 6e476c6dd..878c3b2ea 100644 --- a/applications/external/flipper_i2ctools/views/main_view.h +++ b/applications/external/flipper_i2ctools/views/main_view.h @@ -1,7 +1,7 @@ #include #include #include -#include +#include "i2ctools_icons.h" #include #define APP_NAME "I2C Tools" @@ -41,4 +41,4 @@ typedef struct { void draw_main_view(Canvas* canvas, i2cMainView* main_view); i2cMainView* i2c_main_view_alloc(); -void i2c_main_view_free(i2cMainView* main_view); +void i2c_main_view_free(i2cMainView* main_view); \ No newline at end of file diff --git a/applications/external/flipper_i2ctools/views/scanner_view.h b/applications/external/flipper_i2ctools/views/scanner_view.h index 9b571ed9b..0ce780d5e 100644 --- a/applications/external/flipper_i2ctools/views/scanner_view.h +++ b/applications/external/flipper_i2ctools/views/scanner_view.h @@ -1,10 +1,10 @@ #include #include #include -#include +#include "i2ctools_icons.h" #include #include "../i2cscanner.h" #define SCAN_TEXT "SCAN" -void draw_scanner_view(Canvas* canvas, i2cScanner* i2c_scanner); +void draw_scanner_view(Canvas* canvas, i2cScanner* i2c_scanner); \ No newline at end of file diff --git a/applications/external/flipper_i2ctools/views/sender_view.h b/applications/external/flipper_i2ctools/views/sender_view.h index 3c2000703..a1148e1f8 100644 --- a/applications/external/flipper_i2ctools/views/sender_view.h +++ b/applications/external/flipper_i2ctools/views/sender_view.h @@ -1,10 +1,10 @@ #include #include #include -#include +#include "i2ctools_icons.h" #include #include "../i2csender.h" #define SEND_TEXT "SEND" -void draw_sender_view(Canvas* canvas, i2cSender* i2c_sender); +void draw_sender_view(Canvas* canvas, i2cSender* i2c_sender); \ No newline at end of file diff --git a/applications/external/flipper_i2ctools/views/sniffer_view.h b/applications/external/flipper_i2ctools/views/sniffer_view.h index 1b586d568..fdb817ec3 100644 --- a/applications/external/flipper_i2ctools/views/sniffer_view.h +++ b/applications/external/flipper_i2ctools/views/sniffer_view.h @@ -1,10 +1,10 @@ #include #include #include -#include +#include "i2ctools_icons.h" #include #include "../i2csniffer.h" #define SNIFF_TEXT "SNIFF" -void draw_sniffer_view(Canvas* canvas, i2cSniffer* i2c_sniffer); +void draw_sniffer_view(Canvas* canvas, i2cSniffer* i2c_sniffer); \ No newline at end of file diff --git a/applications/external/flizzer_tracker/application.fam b/applications/external/flizzer_tracker/application.fam index c5b2d2cee..481e41c40 100644 --- a/applications/external/flizzer_tracker/application.fam +++ b/applications/external/flizzer_tracker/application.fam @@ -5,7 +5,6 @@ App( entry_point="flizzer_tracker_app", cdefines=["APP_FLIZZER_TRACKER"], stack_size=2 * 1024, - order=90, fap_version=(0, 2), fap_description="An advanced Flipper Zero chiptune tracker with 4 channels", fap_author="LTVA", diff --git a/applications/external/flizzer_tracker/flizzer_tracker.c b/applications/external/flizzer_tracker/flizzer_tracker.c index 2c0729a43..63f22e32a 100644 --- a/applications/external/flizzer_tracker/flizzer_tracker.c +++ b/applications/external/flizzer_tracker/flizzer_tracker.c @@ -7,7 +7,8 @@ #include "view/pattern_editor.h" #include "font.h" -#include +#include "flizzer_tracker_icons.h" +#include void draw_callback(Canvas* canvas, void* ctx) { TrackerViewModel* model = (TrackerViewModel*)ctx; diff --git a/applications/external/flizzer_tracker/view/instrument_editor.c b/applications/external/flizzer_tracker/view/instrument_editor.c index b931a5de5..4d5463118 100644 --- a/applications/external/flizzer_tracker/view/instrument_editor.c +++ b/applications/external/flizzer_tracker/view/instrument_editor.c @@ -4,7 +4,8 @@ #include "../macros.h" #include "opcode_description.h" -#include +#include "flizzer_tracker_icons.h" +#include void draw_inst_flag( FlizzerTrackerApp* tracker, diff --git a/applications/external/flizzer_tracker/view/pattern_editor.c b/applications/external/flizzer_tracker/view/pattern_editor.c index 19c62d9f9..c4effed56 100644 --- a/applications/external/flizzer_tracker/view/pattern_editor.c +++ b/applications/external/flizzer_tracker/view/pattern_editor.c @@ -1,7 +1,8 @@ #include "pattern_editor.h" #include "../macros.h" -#include +#include "flizzer_tracker_icons.h" +#include #define PATTERN_EDITOR_Y ((tracker->focus == EDIT_PATTERN) ? 4 : (64 - (6 * 5) - 1)) diff --git a/applications/external/game15/application.fam b/applications/external/game15/application.fam index d6b1e10a0..36efe4d26 100644 --- a/applications/external/game15/application.fam +++ b/applications/external/game15/application.fam @@ -6,7 +6,6 @@ App( requires=["gui"], stack_size=1 * 1024, fap_icon="game15_10px.png", - order=30, fap_category="Games", fap_author="@x27", fap_version="1.0", diff --git a/applications/external/game15/game15.c b/applications/external/game15/game15.c index d5d9a3bec..3a8750d75 100644 --- a/applications/external/game15/game15.c +++ b/applications/external/game15/game15.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "sandbox.h" @@ -118,6 +119,7 @@ static bool storage_game_state_load() { storage_common_migrate(storage, EXT_PATH("apps/Games/game15.save"), SAVING_FILENAME); File* file = storage_file_alloc(storage); + uint16_t bytes_readed = 0; if(storage_file_open(file, SAVING_FILENAME, FSAM_READ, FSOM_OPEN_EXISTING)) bytes_readed = storage_file_read(file, &game_state, sizeof(game_state_t)); @@ -456,6 +458,9 @@ int32_t game15_app() { sandbox_init( FPS, (SandboxRenderCallback)render_callback, (SandboxEventHandler)game_event_handler); + // Call dolphin deed on game start + dolphin_deed(DolphinDeedPluginGameStart); + sandbox_loop(); sandbox_free(); game_free(); diff --git a/applications/external/game_2048/application.fam b/applications/external/game_2048/application.fam index 6be28fafd..d78cdfd27 100644 --- a/applications/external/game_2048/application.fam +++ b/applications/external/game_2048/application.fam @@ -1,4 +1,3 @@ -# PLUGIN BY eugene-kirzhanov App( appid="game_2048", name="2048", @@ -8,10 +7,9 @@ App( "gui", ], stack_size=1 * 1024, - order=90, fap_icon="game_2048.png", fap_category="Games", fap_author="@eugene-kirzhanov", - fap_version="1.0", - fap_description="2048 Game", + fap_version="1.1", + fap_description="Play the port of the 2048 game on Flipper Zero.", ) diff --git a/applications/external/game_2048/game_2048.c b/applications/external/game_2048/game_2048.c index 2376f6fcc..48d0200ec 100644 --- a/applications/external/game_2048/game_2048.c +++ b/applications/external/game_2048/game_2048.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "digits.h" #include "array_utils.h" @@ -393,6 +394,9 @@ int32_t game_2048_app() { Gui* gui = furi_record_open(RECORD_GUI); gui_add_view_port(gui, view_port, GuiLayerFullscreen); + // Call dolphin deed on game start + dolphin_deed(DolphinDeedPluginGameStart); + bool is_finished = false; while(!is_finished) { FuriStatus event_status = furi_message_queue_get(event_queue, &input, FuriWaitForever); diff --git a/applications/external/game_of_life/application.fam b/applications/external/game_of_life/application.fam index 0037dbe4e..a4de9ff40 100644 --- a/applications/external/game_of_life/application.fam +++ b/applications/external/game_of_life/application.fam @@ -6,7 +6,6 @@ App( cdefines=["APP_GAMEOFLIFE_GAME"], requires=["gui"], stack_size=2 * 1024, - order=110, fap_icon="golIcon.png", fap_category="Games", fap_author="@tgxn (original by @itsyourbedtime)", diff --git a/applications/external/geiger/flipper_geiger.c b/applications/external/geiger/flipper_geiger.c index a9101a277..58ab08b0e 100644 --- a/applications/external/geiger/flipper_geiger.c +++ b/applications/external/geiger/flipper_geiger.c @@ -10,6 +10,7 @@ #include #include #include + #include #include @@ -35,48 +36,118 @@ typedef struct { typedef struct { FuriMutex* mutex; uint32_t cps, cpm; - uint32_t line[SCREEN_SIZE_X / 2]; + uint32_t line[SCREEN_SIZE_X]; float coef; uint8_t data; + uint8_t zoom; + uint8_t newLinePosition; + uint8_t version; } mutexStruct; static void draw_callback(Canvas* canvas, void* ctx) { furi_assert(ctx); - mutexStruct displayStruct; - mutexStruct* geigerMutex = ctx; - furi_mutex_acquire(geigerMutex->mutex, FuriWaitForever); - memcpy(&displayStruct, geigerMutex, sizeof(mutexStruct)); - furi_mutex_release(geigerMutex->mutex); + mutexStruct* mutexVal = ctx; + mutexStruct mutexDraw; + furi_mutex_acquire(mutexVal->mutex, FuriWaitForever); + memcpy(&mutexDraw, mutexVal, sizeof(mutexStruct)); + furi_mutex_release(mutexVal->mutex); - char buffer[32]; - if(displayStruct.data == 0) - snprintf( - buffer, sizeof(buffer), "%ld cps - %ld cpm", displayStruct.cps, displayStruct.cpm); - else if(displayStruct.data == 1) - snprintf( - buffer, - sizeof(buffer), - "%ld cps - %.2f uSv/h", - displayStruct.cps, - ((double)displayStruct.cpm * (double)CONVERSION_FACTOR)); - else - snprintf( - buffer, - sizeof(buffer), - "%ld cps - %.2f mSv/y", - displayStruct.cps, - (((double)displayStruct.cpm * (double)CONVERSION_FACTOR)) * (double)8.76); + if(mutexDraw.version == 0) { + char buffer[32]; + if(mutexDraw.data == 0) + snprintf(buffer, sizeof(buffer), "%ld cps - %ld cpm", mutexDraw.cps, mutexDraw.cpm); + else if(mutexDraw.data == 1) + snprintf( + buffer, + sizeof(buffer), + "%ld cps - %.2f uSv/h", + mutexDraw.cps, + ((double)mutexDraw.cpm * (double)CONVERSION_FACTOR)); + else if(mutexDraw.data == 2) + snprintf( + buffer, + sizeof(buffer), + "%ld cps - %.2f mSv/y", + mutexDraw.cps, + (((double)mutexDraw.cpm * (double)CONVERSION_FACTOR)) * (double)8.76); + else if(mutexDraw.data == 3) + snprintf( + buffer, + sizeof(buffer), + "%ld cps - %.4f Rad/h", + mutexDraw.cps, + ((double)mutexDraw.cpm * (double)CONVERSION_FACTOR) / (double)10000); + else if(mutexDraw.data == 4) + snprintf( + buffer, + sizeof(buffer), + "%ld cps - %.2f mR/h", + mutexDraw.cps, + ((double)mutexDraw.cpm * (double)CONVERSION_FACTOR) / (double)10); + else + snprintf( + buffer, + sizeof(buffer), + "%ld cps - %.2f uR/h", + mutexDraw.cps, + ((double)mutexDraw.cpm * (double)CONVERSION_FACTOR) * (double)100); - for(int i = 0; i < SCREEN_SIZE_X; i += 2) { - float Y = SCREEN_SIZE_Y - (displayStruct.line[i / 2] * displayStruct.coef); + canvas_set_font(canvas, FontPrimary); + canvas_draw_str_aligned(canvas, 64, 10, AlignCenter, AlignBottom, buffer); - canvas_draw_line(canvas, i, Y, i, SCREEN_SIZE_Y); - canvas_draw_line(canvas, i + 1, Y, i + 1, SCREEN_SIZE_Y); + uint8_t linePosition = mutexDraw.newLinePosition; + + if(mutexDraw.zoom == 0) { + for(int i = 0; i < SCREEN_SIZE_X; i += 8) { + if(linePosition != 0) + linePosition--; + else + linePosition = SCREEN_SIZE_X - 1; + + float Y = SCREEN_SIZE_Y - (mutexDraw.line[linePosition] * mutexDraw.coef); + for(int j = 0; j < 8; j++) + canvas_draw_line(canvas, i + j, Y, i + j, SCREEN_SIZE_Y); + } + } else if(mutexDraw.zoom == 1) { + for(int i = 0; i < SCREEN_SIZE_X; i += 4) { + if(linePosition != 0) + linePosition--; + else + linePosition = SCREEN_SIZE_X - 1; + + float Y = SCREEN_SIZE_Y - (mutexDraw.line[linePosition] * mutexDraw.coef); + for(int j = 0; j < 4; j++) + canvas_draw_line(canvas, i + j, Y, i + j, SCREEN_SIZE_Y); + } + } else if(mutexDraw.zoom == 2) { + for(int i = 0; i < SCREEN_SIZE_X; i += 2) { + if(linePosition != 0) + linePosition--; + else + linePosition = SCREEN_SIZE_X - 1; + + float Y = SCREEN_SIZE_Y - (mutexDraw.line[linePosition] * mutexDraw.coef); + for(int j = 0; j < 2; j++) + canvas_draw_line(canvas, i + j, Y, i + j, SCREEN_SIZE_Y); + } + } else if(mutexDraw.zoom == 3) { + for(int i = 0; i < SCREEN_SIZE_X; i++) { + if(linePosition != 0) + linePosition--; + else + linePosition = SCREEN_SIZE_X - 1; + + float Y = SCREEN_SIZE_Y - (mutexDraw.line[linePosition] * mutexDraw.coef); + canvas_draw_line(canvas, i, Y, i, SCREEN_SIZE_Y); + } + } + } else { + canvas_set_font(canvas, FontPrimary); + canvas_draw_str_aligned(canvas, 64, 10, AlignCenter, AlignBottom, "Geiger Counter"); + canvas_draw_str_aligned(canvas, 64, 20, AlignCenter, AlignBottom, "Version 20230806"); + canvas_draw_str_aligned(canvas, 64, 40, AlignCenter, AlignBottom, "github.com/nmrr"); } - - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 64, 10, AlignCenter, AlignBottom, buffer); } static void input_callback(InputEvent* input_event, void* ctx) { @@ -107,8 +178,7 @@ static void gpiocallback(void* ctx) { furi_message_queue_put(queue, &event, 0); } -int32_t flipper_geiger_app(void* p) { - UNUSED(p); +int32_t flipper_geiger_app() { EventApp event; FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(EventApp)); @@ -118,9 +188,12 @@ int32_t flipper_geiger_app(void* p) { mutexStruct mutexVal; mutexVal.cps = 0; mutexVal.cpm = 0; - for(int i = 0; i < SCREEN_SIZE_X / 2; i++) mutexVal.line[i] = 0; + for(int i = 0; i < SCREEN_SIZE_X; i++) mutexVal.line[i] = 0; mutexVal.coef = 1; mutexVal.data = 0; + mutexVal.zoom = 2; + mutexVal.newLinePosition = 0; + mutexVal.version = 0; uint32_t counter = 0; @@ -131,7 +204,7 @@ int32_t flipper_geiger_app(void* p) { } ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, draw_callback, &mutexVal); + view_port_draw_callback_set(view_port, draw_callback, &mutexVal.mutex); view_port_input_callback_set(view_port, input_callback, event_queue); furi_hal_gpio_add_int_callback(&gpio_ext_pa7, gpiocallback, event_queue); @@ -166,15 +239,16 @@ int32_t flipper_geiger_app(void* p) { if(event_status == FuriStatusOk) { if(event.type == EventTypeInput) { - if(event.input.key == InputKeyBack) { + if(event.input.key == InputKeyBack && event.input.type == InputTypeLong) { break; - } else if(event.input.key == InputKeyOk && event.input.type == InputTypeShort) { + } else if(event.input.key == InputKeyOk && event.input.type == InputTypeLong) { counter = 0; furi_mutex_acquire(mutexVal.mutex, FuriWaitForever); mutexVal.cps = 0; mutexVal.cpm = 0; - for(int i = 0; i < SCREEN_SIZE_X / 2; i++) mutexVal.line[i] = 0; + for(uint8_t i = 0; i < SCREEN_SIZE_X; i++) mutexVal.line[i] = 0; + mutexVal.newLinePosition = 0; screenRefresh = 1; furi_mutex_release(mutexVal.mutex); @@ -215,7 +289,7 @@ int32_t flipper_geiger_app(void* p) { if(mutexVal.data != 0) mutexVal.data--; else - mutexVal.data = 2; + mutexVal.data = 5; screenRefresh = 1; furi_mutex_release(mutexVal.mutex); @@ -223,35 +297,61 @@ int32_t flipper_geiger_app(void* p) { event.input.type == InputTypeShort)) { furi_mutex_acquire(mutexVal.mutex, FuriWaitForever); - if(mutexVal.data != 2) + if(mutexVal.data != 5) mutexVal.data++; else mutexVal.data = 0; + screenRefresh = 1; + furi_mutex_release(mutexVal.mutex); + } else if((event.input.key == InputKeyUp && event.input.type == InputTypeShort)) { + furi_mutex_acquire(mutexVal.mutex, FuriWaitForever); + if(mutexVal.zoom != 0) mutexVal.zoom--; + + screenRefresh = 1; + furi_mutex_release(mutexVal.mutex); + + } else if((event.input.key == InputKeyDown && + event.input.type == InputTypeShort)) { + furi_mutex_acquire(mutexVal.mutex, FuriWaitForever); + if(mutexVal.zoom != 3) mutexVal.zoom++; + + screenRefresh = 1; + furi_mutex_release(mutexVal.mutex); + } else if((event.input.key == InputKeyDown && event.input.type == InputTypeLong)) { + furi_mutex_acquire(mutexVal.mutex, FuriWaitForever); + if(mutexVal.version == 0) + mutexVal.version = 1; + else + mutexVal.version = 0; + screenRefresh = 1; furi_mutex_release(mutexVal.mutex); } } else if(event.type == ClockEventTypeTick) { - furi_mutex_acquire(mutexVal.mutex, FuriWaitForever); - if(recordData == 1) { furi_string_printf(dataString, "%lu,%lu\n", epoch++, counter); stream_write_string(file_stream, dataString); } - for(int i = 0; i < SCREEN_SIZE_X / 2 - 1; i++) - mutexVal.line[SCREEN_SIZE_X / 2 - 1 - i] = - mutexVal.line[SCREEN_SIZE_X / 2 - 2 - i]; + furi_mutex_acquire(mutexVal.mutex, FuriWaitForever); - mutexVal.line[0] = counter; + mutexVal.line[mutexVal.newLinePosition] = counter; mutexVal.cps = counter; counter = 0; - mutexVal.cpm = mutexVal.line[0]; - uint32_t max = mutexVal.line[0]; - for(int i = 1; i < SCREEN_SIZE_X / 2; i++) { - if(i < 60) mutexVal.cpm += mutexVal.line[i]; - if(mutexVal.line[i] > max) max = mutexVal.line[i]; + mutexVal.cpm = mutexVal.line[mutexVal.newLinePosition]; + uint32_t max = mutexVal.line[mutexVal.newLinePosition]; + uint8_t linePosition = mutexVal.newLinePosition; + + for(int i = 1; i < SCREEN_SIZE_X; i++) { + if(linePosition != 0) + linePosition--; + else + linePosition = SCREEN_SIZE_X - 1; + + if(i < 60) mutexVal.cpm += mutexVal.line[linePosition]; + if(mutexVal.line[linePosition] > max) max = mutexVal.line[linePosition]; } if(max > 0) @@ -259,6 +359,11 @@ int32_t flipper_geiger_app(void* p) { else mutexVal.coef = 1; + if(mutexVal.newLinePosition != SCREEN_SIZE_X - 1) + mutexVal.newLinePosition++; + else + mutexVal.newLinePosition = 0; + screenRefresh = 1; furi_mutex_release(mutexVal.mutex); } else if(event.type == EventGPIO) { diff --git a/applications/external/gpioreader_b/application.fam b/applications/external/gpioreader_b/application.fam index 29fe701b6..3e38301ba 100644 --- a/applications/external/gpioreader_b/application.fam +++ b/applications/external/gpioreader_b/application.fam @@ -5,7 +5,6 @@ App( entry_point="gpio_app", requires=["gui"], stack_size=1 * 1024, - order=50, fap_category="GPIO", fap_icon="icon.png", fap_icon_assets="icons", diff --git a/applications/external/gps_nmea_uart/application.fam b/applications/external/gps_nmea_uart/application.fam index c3897e38a..1bc46d535 100644 --- a/applications/external/gps_nmea_uart/application.fam +++ b/applications/external/gps_nmea_uart/application.fam @@ -5,7 +5,6 @@ App( entry_point="gps_app", requires=["gui"], stack_size=1 * 1024, - order=35, fap_icon="gps_10px.png", fap_category="GPIO", fap_author="@ezod & @xMasterX", diff --git a/applications/external/hc_sr04/application.fam b/applications/external/hc_sr04/application.fam index 7bbbaa5be..cbe135194 100644 --- a/applications/external/hc_sr04/application.fam +++ b/applications/external/hc_sr04/application.fam @@ -7,7 +7,6 @@ App( "gui", ], stack_size=2 * 1024, - order=20, fap_icon="dist_sensor10px.png", fap_category="GPIO", fap_author="@xMasterX (first implementation by @Sanqui)", diff --git a/applications/external/heap_defence_game/heap_defence.c b/applications/external/heap_defence_game/heap_defence.c index daf910404..111c22dce 100644 --- a/applications/external/heap_defence_game/heap_defence.c +++ b/applications/external/heap_defence_game/heap_defence.c @@ -14,6 +14,7 @@ #include #include #include +#include #define Y_FIELD_SIZE 6 #define Y_LAST (Y_FIELD_SIZE - 1) @@ -532,6 +533,9 @@ int32_t heap_defence_app(void* p) { game->game_status = 0; game->animation = AnimationPause; + // Call dolphin deed on game start + dolphin_deed(DolphinDeedPluginGameStart); + GameEvent event = {0}; while(event.input.key != InputKeyBack) { if(furi_message_queue_get(event_queue, &event, 100) != FuriStatusOk) { diff --git a/applications/external/hex_editor/application.fam b/applications/external/hex_editor/application.fam index fa7c3f13e..8f8d8c26e 100644 --- a/applications/external/hex_editor/application.fam +++ b/applications/external/hex_editor/application.fam @@ -9,7 +9,6 @@ App( "dialogs", ], stack_size=2 * 1024, - order=20, fap_icon="icons/edit_10px.png", fap_category="Tools", fap_icon_assets="icons", diff --git a/applications/external/hex_viewer/application.fam b/applications/external/hex_viewer/application.fam index be8a7a0dd..821eead69 100644 --- a/applications/external/hex_viewer/application.fam +++ b/applications/external/hex_viewer/application.fam @@ -8,11 +8,10 @@ App( "dialogs", ], stack_size=2 * 1024, - order=20, fap_icon="icons/hex_10px.png", fap_category="Tools", fap_icon_assets="icons", fap_author="@QtRoS", - fap_version="1.0", + fap_version="1.1", fap_description="App allows to view various files as HEX.", ) diff --git a/applications/external/hex_viewer/hex_viewer.c b/applications/external/hex_viewer/hex_viewer.c index 58fedb341..b98f2d867 100644 --- a/applications/external/hex_viewer/hex_viewer.c +++ b/applications/external/hex_viewer/hex_viewer.c @@ -1,7 +1,8 @@ #include #include -#include +#include "hex_viewer_icons.h" +#include #include #include #include @@ -163,7 +164,7 @@ static bool hex_viewer_open_file(HexViewer* hex_viewer, const char* file_path) { FURI_LOG_E(TAG, "Unable to open stream: %s", file_path); isOk = false; break; - } + }; hex_viewer->model->file_size = stream_size(hex_viewer->model->stream); } while(false); diff --git a/applications/external/hid_app/hid.h b/applications/external/hid_app/hid.h index 2b5a8059b..c21d3e265 100644 --- a/applications/external/hid_app/hid.h +++ b/applications/external/hid_app/hid.h @@ -25,9 +25,6 @@ #include "views/hid_tikshorts.h" #include "views/hid_mouse_clicker.h" -#include "hid_icons.h" -#include - #include "hid_path.h" typedef enum { diff --git a/applications/external/hid_app/views/hid_keyboard.c b/applications/external/hid_app/views/hid_keyboard.c index 1c1525ec9..c41c53797 100644 --- a/applications/external/hid_app/views/hid_keyboard.c +++ b/applications/external/hid_app/views/hid_keyboard.c @@ -3,6 +3,8 @@ #include #include #include "../hid.h" +#include "hid_icons.h" +#include #define TAG "HidKeyboard" diff --git a/applications/external/hid_app/views/hid_keynote.c b/applications/external/hid_app/views/hid_keynote.c index e3d5f7a99..ce21bc56b 100644 --- a/applications/external/hid_app/views/hid_keynote.c +++ b/applications/external/hid_app/views/hid_keynote.c @@ -2,6 +2,9 @@ #include #include "../hid.h" +#include "hid_icons.h" +#include + #define TAG "HidKeynote" struct HidKeynote { diff --git a/applications/external/hid_app/views/hid_media.c b/applications/external/hid_app/views/hid_media.c index caf854eb1..037f251fe 100644 --- a/applications/external/hid_app/views/hid_media.c +++ b/applications/external/hid_app/views/hid_media.c @@ -5,6 +5,9 @@ #include #include "../hid.h" +#include "hid_icons.h" +#include + #define TAG "HidMedia" struct HidMedia { diff --git a/applications/external/hid_app/views/hid_mouse.c b/applications/external/hid_app/views/hid_mouse.c index 4c4737155..3fd364ef9 100644 --- a/applications/external/hid_app/views/hid_mouse.c +++ b/applications/external/hid_app/views/hid_mouse.c @@ -2,6 +2,9 @@ #include #include "../hid.h" +#include "hid_icons.h" +#include + #define TAG "HidMouse" struct HidMouse { diff --git a/applications/external/hid_app/views/hid_mouse_clicker.c b/applications/external/hid_app/views/hid_mouse_clicker.c index 6777034ff..b0269738e 100644 --- a/applications/external/hid_app/views/hid_mouse_clicker.c +++ b/applications/external/hid_app/views/hid_mouse_clicker.c @@ -2,6 +2,9 @@ #include #include "../hid.h" +#include "hid_icons.h" +#include + #define TAG "HidMouseClicker" #define DEFAULT_CLICK_RATE 1 #define MAXIMUM_CLICK_RATE 60 diff --git a/applications/external/hid_app/views/hid_mouse_jiggler.c b/applications/external/hid_app/views/hid_mouse_jiggler.c index c2ff93f60..bc71b7da6 100644 --- a/applications/external/hid_app/views/hid_mouse_jiggler.c +++ b/applications/external/hid_app/views/hid_mouse_jiggler.c @@ -2,6 +2,9 @@ #include #include "../hid.h" +#include "hid_icons.h" +#include + #define TAG "HidMouseJiggler" struct HidMouseJiggler { diff --git a/applications/external/hid_app/views/hid_numpad.c b/applications/external/hid_app/views/hid_numpad.c index b342bb38d..1d0c62769 100644 --- a/applications/external/hid_app/views/hid_numpad.c +++ b/applications/external/hid_app/views/hid_numpad.c @@ -3,6 +3,8 @@ #include #include #include "../hid.h" +#include "hid_icons.h" +#include #define TAG "HidNumpad" diff --git a/applications/external/hid_app/views/hid_tikshorts.c b/applications/external/hid_app/views/hid_tikshorts.c index 78e7488f3..6796b3ca6 100644 --- a/applications/external/hid_app/views/hid_tikshorts.c +++ b/applications/external/hid_app/views/hid_tikshorts.c @@ -2,6 +2,9 @@ #include "../hid.h" #include +#include "hid_icons.h" +#include + #define TAG "HidTikShorts" struct HidTikShorts { diff --git a/applications/external/ifttt/application.fam b/applications/external/ifttt/application.fam index 1a86000a4..2f8871e03 100644 --- a/applications/external/ifttt/application.fam +++ b/applications/external/ifttt/application.fam @@ -8,7 +8,6 @@ App( "gui", ], stack_size=2 * 1024, - order=20, fap_icon="icon.png", fap_category="WiFi", ) diff --git a/applications/external/ir_scope/application.fam b/applications/external/ir_scope/application.fam index 00e161d97..ceaa629f7 100644 --- a/applications/external/ir_scope/application.fam +++ b/applications/external/ir_scope/application.fam @@ -3,12 +3,11 @@ App( name="IR Scope", apptype=FlipperAppType.EXTERNAL, entry_point="ir_scope_app", - cdefines=["APP_IR_SCOPE"], requires=["gui"], stack_size=2 * 1024, fap_icon="ir_scope.png", fap_category="Infrared", fap_author="@kallanreed", - fap_version="1.0", + fap_version="1.2", fap_description="App allows to see incoming IR signals.", ) diff --git a/applications/external/jetpack_joyride/application.fam b/applications/external/jetpack_joyride/application.fam index 1b98e11ce..bb4eaa8fb 100644 --- a/applications/external/jetpack_joyride/application.fam +++ b/applications/external/jetpack_joyride/application.fam @@ -8,7 +8,6 @@ App( cdefines=["APP_JETPACK_GAME"], requires=["gui"], stack_size=4 * 1024, - order=100, fap_icon="icon.png", fap_category="Games", fap_icon_assets="assets", diff --git a/applications/external/jetpack_joyride/includes/background_assets.h b/applications/external/jetpack_joyride/includes/background_assets.h index d42fcfd71..21721f03c 100644 --- a/applications/external/jetpack_joyride/includes/background_assets.h +++ b/applications/external/jetpack_joyride/includes/background_assets.h @@ -9,7 +9,8 @@ #include "point.h" #include "states.h" #include "game_sprites.h" -#include +#include "jetpack_joyride_icons.h" +#include #define BG_ASSETS_MAX 3 diff --git a/applications/external/jetpack_joyride/includes/coin.c b/applications/external/jetpack_joyride/includes/coin.c index 7a3811a8c..485e55f1b 100644 --- a/applications/external/jetpack_joyride/includes/coin.c +++ b/applications/external/jetpack_joyride/includes/coin.c @@ -1,7 +1,8 @@ #include #include -#include +#include "jetpack_joyride_icons.h" +#include #include #include "coin.h" diff --git a/applications/external/jetpack_joyride/includes/missile.c b/applications/external/jetpack_joyride/includes/missile.c index af47e8478..8302973a5 100644 --- a/applications/external/jetpack_joyride/includes/missile.c +++ b/applications/external/jetpack_joyride/includes/missile.c @@ -1,7 +1,8 @@ #include #include -#include +#include "jetpack_joyride_icons.h" +#include #include #include "states.h" diff --git a/applications/external/jetpack_joyride/includes/scientist.c b/applications/external/jetpack_joyride/includes/scientist.c index b1a8a14c0..d831b78db 100644 --- a/applications/external/jetpack_joyride/includes/scientist.c +++ b/applications/external/jetpack_joyride/includes/scientist.c @@ -1,7 +1,8 @@ #include "scientist.h" #include "game_sprites.h" -#include +#include "jetpack_joyride_icons.h" +#include #include void scientist_tick(SCIENTIST* const scientists) { diff --git a/applications/external/jetpack_joyride/jetpack.c b/applications/external/jetpack_joyride/jetpack.c index 7969300bd..37443ee90 100644 --- a/applications/external/jetpack_joyride/jetpack.c +++ b/applications/external/jetpack_joyride/jetpack.c @@ -1,6 +1,7 @@ #include -#include +#include "jetpack_joyride_icons.h" +#include #include #include #include @@ -370,4 +371,4 @@ free_and_exit: furi_message_queue_free(event_queue); return return_code; -} +} \ No newline at end of file diff --git a/applications/external/lightmeter/application.fam b/applications/external/lightmeter/application.fam index a1ad9fd0e..83e14b543 100644 --- a/applications/external/lightmeter/application.fam +++ b/applications/external/lightmeter/application.fam @@ -7,7 +7,6 @@ App( "gui", ], stack_size=4 * 1024, - order=90, fap_version=(1, 2), fap_icon="lightmeter.png", fap_category="GPIO", diff --git a/applications/external/lightmeter/docs/README.md b/applications/external/lightmeter/docs/README.md deleted file mode 100644 index e90630c03..000000000 --- a/applications/external/lightmeter/docs/README.md +++ /dev/null @@ -1,17 +0,0 @@ -## Lightmeter app for photography - -An application that suggests settings for your manual camera based on the reading of the ambient light sensor. Can also be used in a pure lux meter mode. - -## Supported sensors - -- BH1750 -- MAX44009 - -## Wiring - -| Sensor | Flipper Zero | -| ------ | ------------ | -| VCC | 3.3V | -| GND | GND | -| SCL | C0 | -| SDA | C1 | diff --git a/applications/external/magspoof/application.fam b/applications/external/magspoof/application.fam index 7a9ad7c60..dd764c584 100644 --- a/applications/external/magspoof/application.fam +++ b/applications/external/magspoof/application.fam @@ -10,12 +10,11 @@ App( "dialogs", ], stack_size=6 * 1024, - order=64, # keep it at the bottom of the list while still WIP fap_icon="icons/mag_10px.png", fap_category="GPIO", fap_icon_assets="icons", fap_version=(0, 5), # major, minor fap_description="WIP MagSpoof port using the RFID subsystem", fap_author="Zachary Weiss", - fap_weburl="https://github.com/hummusec/magspoof_flipper", # Original by zacharyweiss + fap_weburl="https://github.com/zacharyweiss/magspoof_flipper", ) diff --git a/applications/external/magspoof/helpers/mag_helpers.c b/applications/external/magspoof/helpers/mag_helpers.c index 1f7c2ae20..89c451f62 100644 --- a/applications/external/magspoof/helpers/mag_helpers.c +++ b/applications/external/magspoof/helpers/mag_helpers.c @@ -153,7 +153,6 @@ void tx_deinit_rfid() { furi_hal_gpio_write(RFID_PIN_OUT, 0); furi_hal_rfid_pins_reset(); - furi_hal_power_disable_otg(); } void tx_init_rf(int hz) { @@ -187,7 +186,6 @@ bool tx_init(MagSetting* setting) { tx_init_rfid(); break; case MagTxStateGPIO: - furi_hal_power_enable_otg(); // gpio_item_configure_all_pins(GpioModeOutputPushPull); furi_hal_gpio_init(GPIO_PIN_A, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); furi_hal_gpio_init(GPIO_PIN_B, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); @@ -238,7 +236,6 @@ bool tx_deinit(MagSetting* setting) { furi_hal_gpio_init(GPIO_PIN_ENABLE, GpioModeAnalog, GpioPullNo, GpioSpeedLow); //gpio_item_configure_all_pins(GpioModeAnalog); - furi_hal_power_disable_otg(); break; case MagTxStatePiezo: tx_deinit_piezo(); diff --git a/applications/external/magspoof/mag.c b/applications/external/magspoof/mag.c index 6d8bfa3c3..8c821b994 100644 --- a/applications/external/magspoof/mag.c +++ b/applications/external/magspoof/mag.c @@ -168,16 +168,39 @@ int32_t mag_app(void* p) { Mag* mag = mag_alloc(); UNUSED(p); + mag_make_app_folder(mag); + + // Enable 5v power, multiple attempts to avoid issues with power chip protection false triggering + uint8_t attempts = 0; + bool otg_was_enabled = furi_hal_power_is_otg_enabled(); + while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) { + furi_hal_power_enable_otg(); + furi_delay_ms(10); + } + view_dispatcher_attach_to_gui(mag->view_dispatcher, mag->gui, ViewDispatcherTypeFullscreen); scene_manager_next_scene(mag->scene_manager, MagSceneStart); view_dispatcher_run(mag->view_dispatcher); + // Disable 5v power + if(furi_hal_power_is_otg_enabled() && !otg_was_enabled) { + furi_hal_power_disable_otg(); + } + mag_free(mag); return 0; } +void mag_make_app_folder(Mag* mag) { + furi_assert(mag); + + if(!storage_simply_mkdir(mag->storage, MAG_APP_FOLDER)) { + dialog_message_show_storage_error(mag->dialogs, "Cannot create\napp folder"); + } +} + void mag_text_store_set(Mag* mag, const char* text, ...) { furi_assert(mag); va_list args; diff --git a/applications/external/magspoof/mag_device.c b/applications/external/magspoof/mag_device.c index 77e8c2e83..f3be3a5ff 100644 --- a/applications/external/magspoof/mag_device.c +++ b/applications/external/magspoof/mag_device.c @@ -76,6 +76,8 @@ static bool mag_device_save_file( // Make path to file to be saved furi_string_cat_printf(temp_str, "/%s%s", dev_name, extension); } else { + // Create mag directory if necessary + if(!storage_simply_mkdir((mag_dev->storage), MAG_APP_FOLDER)) break; // First remove mag device file if it was saved furi_string_printf(temp_str, "%s/%s%s", folder, dev_name, extension); } diff --git a/applications/external/magspoof/mag_i.h b/applications/external/magspoof/mag_i.h index af6735cca..a57c26e15 100644 --- a/applications/external/magspoof/mag_i.h +++ b/applications/external/magspoof/mag_i.h @@ -92,6 +92,8 @@ void mag_text_store_clear(Mag* mag); void mag_show_loading_popup(void* context, bool show); +void mag_make_app_folder(Mag* mag); + void mag_popup_timeout_callback(void* context); void mag_widget_callback(GuiButtonType result, InputType type, void* context); diff --git a/applications/external/mandelbrot/application.fam b/applications/external/mandelbrot/application.fam index b5a3f4ccc..7c476ced8 100644 --- a/applications/external/mandelbrot/application.fam +++ b/applications/external/mandelbrot/application.fam @@ -6,7 +6,6 @@ App( cdefines=["APP_MANDELBROT_GAME"], requires=["gui"], stack_size=1 * 1024, - order=130, fap_icon="Mandelbrot.png", fap_category="Media", fap_author="@Possibly-Matt", diff --git a/applications/external/mass_storage/application.fam b/applications/external/mass_storage/application.fam index 96cd28aec..66d18422c 100644 --- a/applications/external/mass_storage/application.fam +++ b/applications/external/mass_storage/application.fam @@ -9,6 +9,7 @@ App( ], stack_size=2 * 1024, fap_description="Implements a mass storage device over USB for disk images", + fap_version="1.2", fap_icon="assets/mass_storage_10px.png", fap_icon_assets="assets", fap_category="USB", diff --git a/applications/external/metronome/application.fam b/applications/external/metronome/application.fam index e6439db7b..b5a87a236 100644 --- a/applications/external/metronome/application.fam +++ b/applications/external/metronome/application.fam @@ -8,8 +8,8 @@ App( ], fap_icon="metronome_icon.png", fap_category="Media", + fap_icon_assets="images", stack_size=2 * 1024, - order=20, fap_author="@panki27 & @xMasterX", fap_version="1.0", fap_description="Metronome app", diff --git a/applications/external/metronome/gui_extensions.c b/applications/external/metronome/gui_extensions.c index 18494098e..4c7ad2252 100644 --- a/applications/external/metronome/gui_extensions.c +++ b/applications/external/metronome/gui_extensions.c @@ -1,5 +1,6 @@ #include #include +#include "metronome_icons.h" #include //lib can only do bottom left/right diff --git a/applications/external/metronome/metronome.c b/applications/external/metronome/metronome.c index 46231d66d..a01f4418d 100644 --- a/applications/external/metronome/metronome.c +++ b/applications/external/metronome/metronome.c @@ -178,7 +178,7 @@ static void timer_callback(void* ctx) { case Silent: break; } - } + }; // this is a bit of a kludge... if we are on vibro and unpronounced, stop vibro after half the usual duration switch(metronome_state->output_mode) { diff --git a/applications/external/mfkey32/application.fam b/applications/external/mfkey32/application.fam index 33d932ce9..4d8b3b062 100644 --- a/applications/external/mfkey32/application.fam +++ b/applications/external/mfkey32/application.fam @@ -9,9 +9,11 @@ App( "storage", ], stack_size=1 * 1024, - fap_icon="images/mfkey.png", + fap_description="Mf Classic key finder", + fap_version="1.0", + fap_icon="mfkey.png", fap_category="NFC", - fap_author="noproto", + fap_author="@noproto", fap_icon_assets="images", fap_weburl="https://github.com/noproto/FlipperMfkey", ) diff --git a/applications/external/mfkey32/mfkey.png b/applications/external/mfkey32/mfkey.png new file mode 100644 index 000000000..52ab29efb Binary files /dev/null and b/applications/external/mfkey32/mfkey.png differ diff --git a/applications/external/mfkey32/mfkey32.c b/applications/external/mfkey32/mfkey32.c index 5e790b01f..fc4c9db26 100644 --- a/applications/external/mfkey32/mfkey32.c +++ b/applications/external/mfkey32/mfkey32.c @@ -13,6 +13,7 @@ #include #include #include "mfkey32_icons.h" +#include #include #include #include diff --git a/applications/external/mifare_fuzzer/application.fam b/applications/external/mifare_fuzzer/application.fam index c90212286..5d02b9235 100644 --- a/applications/external/mifare_fuzzer/application.fam +++ b/applications/external/mifare_fuzzer/application.fam @@ -8,7 +8,6 @@ App( "gui", ], stack_size=4 * 1024, - order=30, fap_icon="images/mifare_fuzzer_10px.png", fap_category="NFC", fap_icon_assets="images", diff --git a/applications/external/mifare_nested/application.fam b/applications/external/mifare_nested/application.fam index b8e2aa0dd..a06f7d7ec 100644 --- a/applications/external/mifare_nested/application.fam +++ b/applications/external/mifare_nested/application.fam @@ -5,7 +5,6 @@ App( entry_point="mifare_nested_app", requires=["storage", "gui", "nfc"], stack_size=4 * 1024, - order=30, fap_icon="assets/icon.png", fap_category="NFC", fap_private_libs=[Lib(name="nested"), Lib(name="parity"), Lib(name="crypto1")], diff --git a/applications/external/mifare_nested/mifare_nested_i.h b/applications/external/mifare_nested/mifare_nested_i.h index b13a6c098..324328b44 100644 --- a/applications/external/mifare_nested/mifare_nested_i.h +++ b/applications/external/mifare_nested/mifare_nested_i.h @@ -20,6 +20,7 @@ #include #include #include "mifare_nested_icons.h" +#include #define NESTED_VERSION_APP "1.5.2" #define NESTED_GITHUB_LINK "https://github.com/AloneLiberty/FlipperNested" diff --git a/applications/external/minesweeper/application.fam b/applications/external/minesweeper/application.fam index 07b3e97bb..891bd7801 100644 --- a/applications/external/minesweeper/application.fam +++ b/applications/external/minesweeper/application.fam @@ -7,7 +7,6 @@ App( stack_size=8 * 1024, fap_category="Games", fap_icon="minesweeper_icon.png", - order=35, fap_author="@panki27 & @xMasterX", fap_version="1.0", fap_description="Minesweeper Game", diff --git a/applications/external/minesweeper/minesweeper.c b/applications/external/minesweeper/minesweeper.c index 41fca2b0a..4e92fba33 100644 --- a/applications/external/minesweeper/minesweeper.c +++ b/applications/external/minesweeper/minesweeper.c @@ -7,6 +7,8 @@ #include #include +#include + #include "assets.h" #define PLAYFIELD_WIDTH 16 @@ -236,6 +238,9 @@ static bool game_won(Minesweeper* minesweeper_state) { message, furi_string_get_cstr(tempStr), 64, 32, AlignCenter, AlignCenter); dialog_message_set_buttons(message, NULL, "Play again", NULL); + // Call dolphin deed when we win the game + dolphin_deed(DolphinDeedPluginGameWin); + DialogMessageButton choice = dialog_message_show(minesweeper_state->dialogs, message); dialog_message_free(message); furi_string_free(tempStr); @@ -390,6 +395,9 @@ int32_t minesweeper_app(void* p) { Gui* gui = furi_record_open(RECORD_GUI); gui_add_view_port(gui, view_port, GuiLayerFullscreen); + // Call dolphin deed on game start + dolphin_deed(DolphinDeedPluginGameStart); + PluginEvent event; for(bool processing = true; processing;) { FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); diff --git a/applications/external/morse_code/application.fam b/applications/external/morse_code/application.fam index d46b34628..d39f4738c 100644 --- a/applications/external/morse_code/application.fam +++ b/applications/external/morse_code/application.fam @@ -7,7 +7,6 @@ App( "gui", ], stack_size=1 * 1024, - order=20, fap_icon="morse_code_10px.png", fap_category="Media", fap_author="@wh00hw & @xMasterX", diff --git a/applications/external/multi_converter/application.fam b/applications/external/multi_converter/application.fam index 6844c73b3..51d1c0798 100644 --- a/applications/external/multi_converter/application.fam +++ b/applications/external/multi_converter/application.fam @@ -5,7 +5,6 @@ App( entry_point="multi_converter_app", requires=["gui"], stack_size=1 * 1024, - order=160, fap_icon="converter_10px.png", fap_category="Tools", fap_author="@theisolinearchip", diff --git a/applications/external/multi_dice/application.fam b/applications/external/multi_dice/application.fam index 15f5fe820..6bca3167a 100644 --- a/applications/external/multi_dice/application.fam +++ b/applications/external/multi_dice/application.fam @@ -6,7 +6,6 @@ App( cdefines=["APP_DICE"], requires=["gui"], stack_size=2 * 1024, - order=70, fap_icon="dice.png", fap_category="Games", ) diff --git a/applications/external/music_beeper/application.fam b/applications/external/music_beeper/application.fam index a15af7e32..24a592c4a 100644 --- a/applications/external/music_beeper/application.fam +++ b/applications/external/music_beeper/application.fam @@ -3,14 +3,11 @@ App( name="Music Beeper", apptype=FlipperAppType.EXTERNAL, entry_point="music_beeper_app", - cdefines=["APP_MUSIC_BEEPER"], requires=[ "gui", "dialogs", ], - provides=["music_beeper_start"], stack_size=2 * 1024, - order=45, fap_icon="music_10px.png", fap_icon_assets="icons", fap_category="Media", diff --git a/applications/external/music_player/application.fam b/applications/external/music_player/application.fam index 4d0858494..24ccb9a70 100644 --- a/applications/external/music_player/application.fam +++ b/applications/external/music_player/application.fam @@ -8,8 +8,8 @@ App( "dialogs", ], stack_size=2 * 1024, - order=45, fap_icon="music_10px.png", fap_category="Media", + fap_icon_assets="icons", fap_libs=["music_worker"], ) diff --git a/applications/external/music_player/music_player.c b/applications/external/music_player/music_player.c index 181eb60d6..aaec81346 100644 --- a/applications/external/music_player/music_player.c +++ b/applications/external/music_player/music_player.c @@ -3,6 +3,7 @@ #include #include +#include "music_player_icons.h" #include #include #include diff --git a/applications/external/music_tracker/application.fam b/applications/external/music_tracker/application.fam index 6c78a9bf6..5aba35cd3 100644 --- a/applications/external/music_tracker/application.fam +++ b/applications/external/music_tracker/application.fam @@ -7,7 +7,6 @@ App( "gui", ], stack_size=4 * 1024, - order=20, fap_icon="zero_tracker.png", fap_category="Media", fap_author="@DrZlo13", diff --git a/applications/external/nfc_magic/application.fam b/applications/external/nfc_magic/application.fam index 83a148f21..01c6dfaa8 100644 --- a/applications/external/nfc_magic/application.fam +++ b/applications/external/nfc_magic/application.fam @@ -9,7 +9,6 @@ App( "gui", ], stack_size=4 * 1024, - order=30, fap_icon="Nfc_10px.png", fap_category="NFC", fap_private_libs=[ diff --git a/applications/external/nfc_rfid_detector/application.fam b/applications/external/nfc_rfid_detector/application.fam index 70c91bc84..ffed6967a 100644 --- a/applications/external/nfc_rfid_detector/application.fam +++ b/applications/external/nfc_rfid_detector/application.fam @@ -6,8 +6,10 @@ App( entry_point="nfc_rfid_detector_app", requires=["gui"], stack_size=4 * 1024, - order=50, + fap_description="Identify the reader type: NFC (13 MHz) and/or RFID (125 KHz).", + fap_version="1.0", fap_icon="nfc_rfid_detector_10px.png", fap_category="Tools", fap_icon_assets="images", + fap_author="SkorP", ) diff --git a/applications/external/nfc_rfid_detector/views/nfc_rfid_detector_view_field_presence.c b/applications/external/nfc_rfid_detector/views/nfc_rfid_detector_view_field_presence.c index faf253977..cf8ca936c 100644 --- a/applications/external/nfc_rfid_detector/views/nfc_rfid_detector_view_field_presence.c +++ b/applications/external/nfc_rfid_detector/views/nfc_rfid_detector_view_field_presence.c @@ -1,6 +1,6 @@ #include "nfc_rfid_detector_view_field_presence.h" #include "../nfc_rfid_detector_app_i.h" -#include +#include "nfc_rfid_detector_icons.h" #include #include diff --git a/applications/external/nightstand/application.fam b/applications/external/nightstand/application.fam index e94e24cf2..380c34b16 100644 --- a/applications/external/nightstand/application.fam +++ b/applications/external/nightstand/application.fam @@ -7,7 +7,6 @@ App( stack_size=2 * 1024, fap_icon="clock.png", fap_category="Tools", - order=81, fap_author="@nymda & @Willy-JL", fap_weburl="https://github.com/nymda/FlipperNightStand", fap_version="1.0", diff --git a/applications/external/nrf24batch/application.fam b/applications/external/nrf24batch/application.fam index ff8e5546e..aff3ffd30 100644 --- a/applications/external/nrf24batch/application.fam +++ b/applications/external/nrf24batch/application.fam @@ -6,7 +6,6 @@ App( cdefines=["APP_NRF24BATCH"], requires=["gui"], stack_size=2 * 1024, - order=60, fap_icon="nrf24batch_10px.png", fap_category="GPIO", fap_private_libs=[ diff --git a/applications/external/nrf24batch/lib/nrf24/nrf24.c b/applications/external/nrf24batch/lib/nrf24/nrf24.c index be1b6ddc0..e074860ed 100644 --- a/applications/external/nrf24batch/lib/nrf24/nrf24.c +++ b/applications/external/nrf24batch/lib/nrf24/nrf24.c @@ -381,4 +381,4 @@ uint8_t nrf24_set_mac(uint8_t mac_addr, uint8_t* mac, uint8_t mlen) { uint8_t addr[5]; for(int i = 0; i < mlen; i++) addr[i] = mac[mlen - i - 1]; return nrf24_write_buf_reg(nrf24_HANDLE, mac_addr, addr, mlen); -} \ No newline at end of file +} diff --git a/applications/external/nrf24batch/lib/nrf24/nrf24.h b/applications/external/nrf24batch/lib/nrf24/nrf24.h index 5e6657caf..605513d4b 100644 --- a/applications/external/nrf24batch/lib/nrf24/nrf24.h +++ b/applications/external/nrf24batch/lib/nrf24/nrf24.h @@ -389,4 +389,4 @@ uint32_t bytes_to_int32(uint8_t* bytes, bool bigendian); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/external/nrf24batch/nrf24batch.c b/applications/external/nrf24batch/nrf24batch.c index 81225fd2b..1eb90c3c2 100644 --- a/applications/external/nrf24batch/nrf24batch.c +++ b/applications/external/nrf24batch/nrf24batch.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include diff --git a/applications/external/nrf24channelscanner/application.fam b/applications/external/nrf24channelscanner/application.fam index af773a1f0..3a7e9bf8c 100644 --- a/applications/external/nrf24channelscanner/application.fam +++ b/applications/external/nrf24channelscanner/application.fam @@ -1,6 +1,6 @@ App( appid="nrf24channelscanner", - name="[NRF24] Channel scanner", + name="[NRF24] Channel Scanner", apptype=FlipperAppType.EXTERNAL, entry_point="nrf24channelscanner_main", stack_size=2 * 1024, diff --git a/applications/external/nrf24channelscanner/images/Ok_btn_9x9.png b/applications/external/nrf24channelscanner/images/Ok_btn_9x9.png deleted file mode 100644 index 978ec1e83..000000000 Binary files a/applications/external/nrf24channelscanner/images/Ok_btn_9x9.png and /dev/null differ diff --git a/applications/external/nrf24channelscanner/images/Pin_back_arrow_10x8.png b/applications/external/nrf24channelscanner/images/Pin_back_arrow_10x8.png deleted file mode 100644 index e46cc5834..000000000 Binary files a/applications/external/nrf24channelscanner/images/Pin_back_arrow_10x8.png and /dev/null differ diff --git a/applications/external/nrf24channelscanner/lib/nrf24/nrf24.c b/applications/external/nrf24channelscanner/lib/nrf24/nrf24.c index 611a5dbda..2307d6daf 100644 --- a/applications/external/nrf24channelscanner/lib/nrf24/nrf24.c +++ b/applications/external/nrf24channelscanner/lib/nrf24/nrf24.c @@ -114,4 +114,4 @@ bool nrf24_check_connected(FuriHalSpiBusHandle* handle) { } else { return false; } -} \ No newline at end of file +} diff --git a/applications/external/nrf24channelscanner/lib/nrf24/nrf24.h b/applications/external/nrf24channelscanner/lib/nrf24/nrf24.h index cd1bab2f1..fdbdb0e3f 100644 --- a/applications/external/nrf24channelscanner/lib/nrf24/nrf24.h +++ b/applications/external/nrf24channelscanner/lib/nrf24/nrf24.h @@ -126,4 +126,4 @@ bool nrf24_check_connected(FuriHalSpiBusHandle* handle); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/external/nrf24channelscanner/nrf24channelscanner.c b/applications/external/nrf24channelscanner/nrf24channelscanner.c index 39749e77a..cfe64bd32 100644 --- a/applications/external/nrf24channelscanner/nrf24channelscanner.c +++ b/applications/external/nrf24channelscanner/nrf24channelscanner.c @@ -7,6 +7,7 @@ #include #include #include "nrf24channelscanner_icons.h" +#include const uint8_t num_channels = 128; static uint8_t nrf24values[128] = {0}; //to store channel data diff --git a/applications/external/nrf24mousejacker/application.fam b/applications/external/nrf24mousejacker/application.fam index f5a9b9dbc..30de60b5d 100644 --- a/applications/external/nrf24mousejacker/application.fam +++ b/applications/external/nrf24mousejacker/application.fam @@ -8,12 +8,12 @@ App( "dialogs", ], stack_size=2 * 1024, - order=60, fap_icon="mouse_10px.png", fap_category="GPIO", fap_author="@mothball187 & @xMasterX", fap_version="1.0", fap_description="App works with NRF24 Sniffer app to perform mousejack attacks", + fap_icon_assets="images", fap_private_libs=[ Lib( name="nrf24", diff --git a/applications/external/nrf24mousejacker/lib/nrf24/nrf24.h b/applications/external/nrf24mousejacker/lib/nrf24/nrf24.h index c61aafffb..58dbad0c8 100644 --- a/applications/external/nrf24mousejacker/lib/nrf24/nrf24.h +++ b/applications/external/nrf24mousejacker/lib/nrf24/nrf24.h @@ -373,4 +373,4 @@ bool nrf24_check_connected(FuriHalSpiBusHandle* handle); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/external/nrf24mousejacker/mousejacker.c b/applications/external/nrf24mousejacker/mousejacker.c index 8f2914c62..02d91f788 100644 --- a/applications/external/nrf24mousejacker/mousejacker.c +++ b/applications/external/nrf24mousejacker/mousejacker.c @@ -11,6 +11,7 @@ #include #include #include "mousejacker_ducky.h" +#include "nrf24mousejacker_icons.h" #include #define TAG "mousejacker" diff --git a/applications/external/nrf24scan/application.fam b/applications/external/nrf24scan/application.fam index 1be252f7c..5ad617ad4 100644 --- a/applications/external/nrf24scan/application.fam +++ b/applications/external/nrf24scan/application.fam @@ -6,7 +6,6 @@ App( cdefines=["APP_NRF24SCAN"], requires=["gui"], stack_size=2 * 1024, - order=60, fap_icon="nrf24scan_10px.png", fap_category="GPIO", fap_private_libs=[ diff --git a/applications/external/nrf24scan/lib/nrf24/nrf24.c b/applications/external/nrf24scan/lib/nrf24/nrf24.c index 284541426..acd0130c7 100644 --- a/applications/external/nrf24scan/lib/nrf24/nrf24.c +++ b/applications/external/nrf24scan/lib/nrf24/nrf24.c @@ -553,4 +553,4 @@ uint8_t nrf24_set_mac(uint8_t mac_addr, uint8_t* mac, uint8_t mlen) { uint8_t addr[5]; for(int i = 0; i < mlen; i++) addr[i] = mac[mlen - i - 1]; return nrf24_write_buf_reg(nrf24_HANDLE, mac_addr, addr, mlen); -} \ No newline at end of file +} diff --git a/applications/external/nrf24scan/lib/nrf24/nrf24.h b/applications/external/nrf24scan/lib/nrf24/nrf24.h index d077f1da3..d5fdced3b 100644 --- a/applications/external/nrf24scan/lib/nrf24/nrf24.h +++ b/applications/external/nrf24scan/lib/nrf24/nrf24.h @@ -384,4 +384,4 @@ uint32_t bytes_to_int32(uint8_t* bytes, bool bigendian); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/external/nrf24scan/nrf24scan.c b/applications/external/nrf24scan/nrf24scan.c index d56ee332e..1a60ce36d 100644 --- a/applications/external/nrf24scan/nrf24scan.c +++ b/applications/external/nrf24scan/nrf24scan.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include diff --git a/applications/external/nrf24sniff/application.fam b/applications/external/nrf24sniff/application.fam index 244677e38..98be7d06e 100644 --- a/applications/external/nrf24sniff/application.fam +++ b/applications/external/nrf24sniff/application.fam @@ -5,7 +5,6 @@ App( entry_point="nrfsniff_app", requires=["gui"], stack_size=2 * 1024, - order=60, fap_icon="nrfsniff_10px.png", fap_category="GPIO", fap_author="@mothball187 & @xMasterX", diff --git a/applications/external/nrf24sniff/lib/nrf24/nrf24.c b/applications/external/nrf24sniff/lib/nrf24/nrf24.c index d85196e86..8b39cf5eb 100644 --- a/applications/external/nrf24sniff/lib/nrf24/nrf24.c +++ b/applications/external/nrf24sniff/lib/nrf24/nrf24.c @@ -543,4 +543,4 @@ bool nrf24_check_connected(FuriHalSpiBusHandle* handle) { } else { return false; } -} \ No newline at end of file +} diff --git a/applications/external/nrf24sniff/lib/nrf24/nrf24.h b/applications/external/nrf24sniff/lib/nrf24/nrf24.h index c61aafffb..58dbad0c8 100644 --- a/applications/external/nrf24sniff/lib/nrf24/nrf24.h +++ b/applications/external/nrf24sniff/lib/nrf24/nrf24.h @@ -373,4 +373,4 @@ bool nrf24_check_connected(FuriHalSpiBusHandle* handle); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/applications/external/nrf24sniff/nrfsniff.c b/applications/external/nrf24sniff/nrfsniff.c index 1b761aacb..bc58602ff 100644 --- a/applications/external/nrf24sniff/nrfsniff.c +++ b/applications/external/nrf24sniff/nrfsniff.c @@ -10,7 +10,7 @@ #define LOGITECH_MAX_CHANNEL 85 #define COUNT_THRESHOLD 2 -#define DEFAULT_SAMPLE_TIME 4000 +#define DEFAULT_SAMPLE_TIME 8000 #define MAX_ADDRS 100 #define MAX_CONFIRMED 32 @@ -350,10 +350,6 @@ int32_t nrfsniff_app(void* p) { storage_common_migrate(storage, EXT_PATH("nrfsniff"), NRFSNIFF_APP_PATH_FOLDER); storage_common_mkdir(storage, NRFSNIFF_APP_PATH_FOLDER); - while(!furi_hal_speaker_acquire(100)) { - furi_delay_ms(100); - } - PluginEvent event; for(bool processing = true; processing;) { FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); @@ -459,7 +455,6 @@ int32_t nrfsniff_app(void* p) { target_rate = 8; // rate can be either 8 (2Mbps) or 0 (1Mbps) sniffing_state = false; nrf24_deinit(); - furi_hal_speaker_release(); view_port_enabled_set(view_port, false); gui_remove_view_port(gui, view_port); furi_record_close(RECORD_GUI); diff --git a/applications/external/ocarina/application.fam b/applications/external/ocarina/application.fam index 552adfdeb..572aa1679 100644 --- a/applications/external/ocarina/application.fam +++ b/applications/external/ocarina/application.fam @@ -6,7 +6,6 @@ App( cdefines=["APP_OCARINA"], requires=["gui"], stack_size=1 * 1024, - order=30, fap_icon="music_10px.png", fap_category="Media", fap_icon_assets="icons", diff --git a/applications/external/orgasmotron/application.fam b/applications/external/orgasmotron/application.fam index b4c191a8a..f58a4a734 100644 --- a/applications/external/orgasmotron/application.fam +++ b/applications/external/orgasmotron/application.fam @@ -6,7 +6,6 @@ App( cdefines=["ORGASMOTRON"], requires=["gui"], stack_size=1 * 1024, - order=20, fap_icon="orgasmotron_10px.png", fap_category="Tools", ) diff --git a/applications/external/paint/application.fam b/applications/external/paint/application.fam index a6f154bac..e5dec6040 100644 --- a/applications/external/paint/application.fam +++ b/applications/external/paint/application.fam @@ -6,7 +6,6 @@ App( cdefines=["APP_PAINT"], requires=["gui"], stack_size=2 * 1024, - order=175, fap_icon="paintIcon.png", fap_category="Media", fap_author="@n-o-T-I-n-s-a-n-e", diff --git a/applications/external/picopass/application.fam b/applications/external/picopass/application.fam index b14427f2e..896d3cf74 100644 --- a/applications/external/picopass/application.fam +++ b/applications/external/picopass/application.fam @@ -1,6 +1,6 @@ App( appid="picopass", - name="PicoPass", + name="[iClass] PicoPass", apptype=FlipperAppType.EXTERNAL, targets=["f7"], entry_point="picopass_app", @@ -9,7 +9,8 @@ App( "gui", ], stack_size=4 * 1024, - order=30, + fap_description="App to communicate with NFC tags using the PicoPass(iClass) format", + fap_version="1.2", fap_icon="125_10px.png", fap_category="NFC", fap_libs=["mbedtls"], @@ -18,4 +19,6 @@ App( name="loclass", ), ], + fap_icon_assets="icons", + fap_file_assets="files", ) diff --git a/applications/external/picopass/files/iclass_elite_dict.txt b/applications/external/picopass/files/iclass_elite_dict.txt new file mode 100644 index 000000000..908889aec --- /dev/null +++ b/applications/external/picopass/files/iclass_elite_dict.txt @@ -0,0 +1,41 @@ + +## From https://github.com/RfidResearchGroup/proxmark3/blob/master/client/dictionaries/iclass_default_keys.dic + +# key1/Kc from PicoPass 2k documentation +7665544332211000 +# SAGEM +0123456789ABCDEF +# PicoPass Default Exchange Key +5CBCF1DA45D5FB4F +# From HID multiclassSE reader +31ad7ebd2f282168 +# From pastebin: https://pastebin.com/uHqpjiuU +6EFD46EFCBB3C875 +E033CA419AEE43F9 + +# default picopass KD / Page 0 / Book 1 +FDCB5A52EA8F3090 +237FF9079863DF44 +5ADC25FB27181D32 +83B881F2936B2E49 +43644E61EE866BA5 +897034143D016080 +82D17B44C0122963 +4895CA7DE65E2025 +DADAD4C57BE271B7 +E41E9EDEF5719ABF +293D275EC3AF9C7F +C3C169251B8A70FB +F41DAF58B20C8B91 +28877A609EC0DD2B +66584C91EE80D5E5 +C1B74D7478053AE2 + +# default iCLASS RFIDeas +6B65797374726B72 + +# CTF key +5C100DF7042EAE64 + +# iCopy-X DRM key (iCE product) +2020666666668888 diff --git a/applications/external/picopass/files/iclass_standard_dict.txt b/applications/external/picopass/files/iclass_standard_dict.txt new file mode 100644 index 000000000..46808ef60 --- /dev/null +++ b/applications/external/picopass/files/iclass_standard_dict.txt @@ -0,0 +1,47 @@ + +## From https://github.com/RfidResearchGroup/proxmark3/blob/master/client/dictionaries/iclass_default_keys.dic + +# AA1 +AEA684A6DAB23278 +# key1/Kc from PicoPass 2k documentation +7665544332211000 +# SAGEM +0123456789ABCDEF +# from loclass demo file. +5b7c62c491c11b39 +# Kd from PicoPass 2k documentation +F0E1D2C3B4A59687 +# PicoPass Default Exchange Key +5CBCF1DA45D5FB4F +# From HID multiclassSE reader +31ad7ebd2f282168 +# From pastebin: https://pastebin.com/uHqpjiuU +6EFD46EFCBB3C875 +E033CA419AEE43F9 + +# iCopy-x DRM keys +# iCL tags +2020666666668888 +# iCS tags reversed from the SOs +6666202066668888 + +# default picopass KD / Page 0 / Book 1 +FDCB5A52EA8F3090 +237FF9079863DF44 +5ADC25FB27181D32 +83B881F2936B2E49 +43644E61EE866BA5 +897034143D016080 +82D17B44C0122963 +4895CA7DE65E2025 +DADAD4C57BE271B7 +E41E9EDEF5719ABF +293D275EC3AF9C7F +C3C169251B8A70FB +F41DAF58B20C8B91 +28877A609EC0DD2B +66584C91EE80D5E5 +C1B74D7478053AE2 + +# default iCLASS RFIDeas +6B65797374726B72 diff --git a/applications/external/picopass/helpers/iclass_elite_dict.c b/applications/external/picopass/helpers/iclass_elite_dict.c index f92dce0aa..5f0f41f85 100644 --- a/applications/external/picopass/helpers/iclass_elite_dict.c +++ b/applications/external/picopass/helpers/iclass_elite_dict.c @@ -3,9 +3,9 @@ #include #include -#define ICLASS_ELITE_DICT_FLIPPER_NAME APP_DATA_PATH("assets/iclass_elite_dict.txt") +#define ICLASS_ELITE_DICT_FLIPPER_NAME APP_ASSETS_PATH("iclass_elite_dict.txt") +#define ICLASS_STANDARD_DICT_FLIPPER_NAME APP_ASSETS_PATH("iclass_standard_dict.txt") #define ICLASS_ELITE_DICT_USER_NAME APP_DATA_PATH("assets/iclass_elite_dict_user.txt") -#define ICLASS_STANDARD_DICT_FLIPPER_NAME APP_DATA_PATH("assets/iclass_standard_dict.txt") #define TAG "IclassEliteDict" diff --git a/applications/external/picopass/picopass.c b/applications/external/picopass/picopass.c index 8b55342ed..13f6ae5fb 100644 --- a/applications/external/picopass/picopass.c +++ b/applications/external/picopass/picopass.c @@ -68,6 +68,13 @@ Picopass* picopass_alloc() { PicopassViewTextInput, text_input_get_view(picopass->text_input)); + // Byte Input + picopass->byte_input = byte_input_alloc(); + view_dispatcher_add_view( + picopass->view_dispatcher, + PicopassViewByteInput, + byte_input_get_view(picopass->byte_input)); + // Custom Widget picopass->widget = widget_alloc(); view_dispatcher_add_view( @@ -109,6 +116,10 @@ void picopass_free(Picopass* picopass) { view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewTextInput); text_input_free(picopass->text_input); + // ByteInput + view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewByteInput); + byte_input_free(picopass->byte_input); + // Custom Widget view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewWidget); widget_free(picopass->widget); diff --git a/applications/external/picopass/picopass_device.c b/applications/external/picopass/picopass_device.c index 3502f253e..dbb9b9e1b 100644 --- a/applications/external/picopass/picopass_device.c +++ b/applications/external/picopass/picopass_device.c @@ -2,6 +2,7 @@ #include #include +#include "picopass_icons.h" #include #define TAG "PicopassDevice" @@ -356,8 +357,8 @@ ReturnCode picopass_device_parse_credential(PicopassBlock* AA1, PicopassPacs* pa return ERR_NONE; } -ReturnCode picopass_device_parse_wiegand(uint8_t* data, PicopassWiegandRecord* record) { - uint32_t* halves = (uint32_t*)data; +ReturnCode picopass_device_parse_wiegand(uint8_t* credential, PicopassWiegandRecord* record) { + uint32_t* halves = (uint32_t*)credential; if(halves[0] == 0) { uint8_t leading0s = __builtin_clz(REVERSE_BYTES_U32(halves[1])); record->bitLength = 31 - leading0s; @@ -367,8 +368,16 @@ ReturnCode picopass_device_parse_wiegand(uint8_t* data, PicopassWiegandRecord* r } FURI_LOG_D(TAG, "bitLength: %d", record->bitLength); + // Remove sentinel bit from credential. Byteswapping to handle array of bytes vs 64bit value + uint64_t sentinel = __builtin_bswap64(1ULL << record->bitLength); + uint64_t swapped = 0; + memcpy(&swapped, credential, sizeof(uint64_t)); + swapped = swapped ^ sentinel; + memcpy(credential, &swapped, sizeof(uint64_t)); + FURI_LOG_D(TAG, "PACS: (%d) %016llx", record->bitLength, swapped); + if(record->bitLength == 26) { - uint8_t* v4 = data + 4; + uint8_t* v4 = credential + 4; uint32_t bot = v4[3] | (v4[2] << 8) | (v4[1] << 16) | (v4[0] << 24); record->CardNumber = (bot >> 1) & 0xFFFF; diff --git a/applications/external/picopass/picopass_i.h b/applications/external/picopass/picopass_i.h index 88c2140ee..0fc928610 100644 --- a/applications/external/picopass/picopass_i.h +++ b/applications/external/picopass/picopass_i.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -26,6 +27,7 @@ #include #include +#include "picopass_icons.h" #include #define PICOPASS_TEXT_STORE_SIZE 128 @@ -60,12 +62,14 @@ struct Picopass { char text_store[PICOPASS_TEXT_STORE_SIZE + 1]; FuriString* text_box_store; + uint8_t byte_input_store[RFAL_PICOPASS_BLOCK_LEN]; // Common Views Submenu* submenu; Popup* popup; Loading* loading; TextInput* text_input; + ByteInput* byte_input; Widget* widget; DictAttack* dict_attack; Loclass* loclass; @@ -76,6 +80,7 @@ typedef enum { PicopassViewPopup, PicopassViewLoading, PicopassViewTextInput, + PicopassViewByteInput, PicopassViewWidget, PicopassViewDictAttack, PicopassViewLoclass, diff --git a/applications/external/picopass/picopass_worker.c b/applications/external/picopass/picopass_worker.c index 25ba7ebba..a0aac6231 100644 --- a/applications/external/picopass/picopass_worker.c +++ b/applications/external/picopass/picopass_worker.c @@ -21,8 +21,8 @@ static const uint8_t loclass_csns[LOCLASS_NUM_CSNS][RFAL_PICOPASS_BLOCK_LEN] = { }; static void picopass_worker_enable_field() { - furi_hal_nfc_ll_txrx_on(); furi_hal_nfc_exit_sleep(); + furi_hal_nfc_ll_txrx_on(); furi_hal_nfc_ll_poll(); } @@ -130,7 +130,7 @@ ReturnCode picopass_detect_card(int timeout) { err = rfalPicoPassPollerCheckPresence(); if(err != ERR_RF_COLLISION) { - //FURI_LOG_E(TAG, "rfalPicoPassPollerCheckPresence error %d", err); + FURI_LOG_E(TAG, "rfalPicoPassPollerCheckPresence error %d", err); return err; } @@ -1057,7 +1057,9 @@ static void picopass_emu_handle_packet( if(memcmp(nfcv_data->frame + 5, rmac, 4)) { // Bad MAC from reader, do not send a response. FURI_LOG_I(TAG, "Got bad MAC from reader"); +#ifndef PICOPASS_DEBUG_IGNORE_BAD_RMAC return; +#endif } // CHIPRESPONSE(4) @@ -1196,6 +1198,8 @@ static void picopass_emu_handle_packet( } void picopass_worker_emulate(PicopassWorker* picopass_worker, bool loclass_mode) { + furi_hal_nfc_exit_sleep(); + FuriHalNfcTxRxContext tx_rx = {}; PicopassEmulatorCtx emu_ctx = { .state = PicopassEmulatorStateIdle, diff --git a/applications/external/picopass/rfal_picopass.c b/applications/external/picopass/rfal_picopass.c index 983a11eab..1d45a48dc 100644 --- a/applications/external/picopass/rfal_picopass.c +++ b/applications/external/picopass/rfal_picopass.c @@ -47,7 +47,7 @@ FuriHalNfcReturn rfalPicoPassPollerInitialize(void) { FuriHalNfcModePollPicopass, FuriHalNfcBitrate26p48, FuriHalNfcBitrate26p48); if(ret != FuriHalNfcReturnOk) { return ret; - } + }; furi_hal_nfc_ll_set_error_handling(FuriHalNfcErrorHandlingNfc); furi_hal_nfc_ll_set_guard_time(FURI_HAL_NFC_LL_GT_PICOPASS); diff --git a/applications/external/picopass/scenes/picopass_scene_card_menu.c b/applications/external/picopass/scenes/picopass_scene_card_menu.c index fe63f7c86..fa4515db3 100644 --- a/applications/external/picopass/scenes/picopass_scene_card_menu.c +++ b/applications/external/picopass/scenes/picopass_scene_card_menu.c @@ -4,6 +4,8 @@ enum SubmenuIndex { SubmenuIndexSave, SubmenuIndexSaveAsLF, SubmenuIndexChangeKey, + SubmenuIndexWrite, + SubmenuIndexEmulate, }; void picopass_scene_card_menu_submenu_callback(void* context, uint32_t index) { @@ -26,6 +28,14 @@ void picopass_scene_card_menu_on_enter(void* context) { picopass_scene_card_menu_submenu_callback, picopass); } + submenu_add_item( + submenu, "Write", SubmenuIndexWrite, picopass_scene_card_menu_submenu_callback, picopass); + submenu_add_item( + submenu, + "Emulate", + SubmenuIndexEmulate, + picopass_scene_card_menu_submenu_callback, + picopass); submenu_add_item( submenu, "Change Key", @@ -57,6 +67,12 @@ bool picopass_scene_card_menu_on_event(void* context, SceneManagerEvent event) { picopass->dev->format = PicopassDeviceSaveFormatLF; scene_manager_next_scene(picopass->scene_manager, PicopassSceneSaveName); consumed = true; + } else if(event.event == SubmenuIndexWrite) { + scene_manager_next_scene(picopass->scene_manager, PicopassSceneWriteCard); + consumed = true; + } else if(event.event == SubmenuIndexEmulate) { + scene_manager_next_scene(picopass->scene_manager, PicopassSceneEmulate); + consumed = true; } else if(event.event == SubmenuIndexChangeKey) { scene_manager_set_scene_state( picopass->scene_manager, PicopassSceneCardMenu, SubmenuIndexChangeKey); diff --git a/applications/external/picopass/scenes/picopass_scene_config.h b/applications/external/picopass/scenes/picopass_scene_config.h index 6156ed689..3241c2344 100644 --- a/applications/external/picopass/scenes/picopass_scene_config.h +++ b/applications/external/picopass/scenes/picopass_scene_config.h @@ -11,9 +11,11 @@ ADD_SCENE(picopass, delete, Delete) ADD_SCENE(picopass, delete_success, DeleteSuccess) ADD_SCENE(picopass, write_card, WriteCard) ADD_SCENE(picopass, write_card_success, WriteCardSuccess) +ADD_SCENE(picopass, write_card_failure, WriteCardFailure) ADD_SCENE(picopass, read_factory_success, ReadFactorySuccess) ADD_SCENE(picopass, write_key, WriteKey) ADD_SCENE(picopass, key_menu, KeyMenu) ADD_SCENE(picopass, elite_dict_attack, EliteDictAttack) ADD_SCENE(picopass, emulate, Emulate) ADD_SCENE(picopass, loclass, Loclass) +ADD_SCENE(picopass, key_input, KeyInput) diff --git a/applications/external/picopass/scenes/picopass_scene_device_info.c b/applications/external/picopass/scenes/picopass_scene_device_info.c index 41d0bad81..60ed6ed94 100644 --- a/applications/external/picopass/scenes/picopass_scene_device_info.c +++ b/applications/external/picopass/scenes/picopass_scene_device_info.c @@ -17,7 +17,6 @@ void picopass_scene_device_info_on_enter(void* context) { FuriString* csn_str = furi_string_alloc_set("CSN:"); FuriString* credential_str = furi_string_alloc(); FuriString* wiegand_str = furi_string_alloc(); - FuriString* sio_str = furi_string_alloc(); dolphin_deed(DolphinDeedNfcReadSuccess); @@ -43,7 +42,7 @@ void picopass_scene_device_info_on_enter(void* context) { } furi_string_set(credential_str, ""); for(uint8_t i = RFAL_PICOPASS_BLOCK_LEN - bytesLength; i < RFAL_PICOPASS_BLOCK_LEN; i++) { - furi_string_cat_printf(credential_str, " %02X", pacs->credential[i]); + furi_string_cat_printf(credential_str, "%02X", pacs->credential[i]); } if(pacs->record.valid) { @@ -54,7 +53,7 @@ void picopass_scene_device_info_on_enter(void* context) { } if(pacs->sio) { - furi_string_cat_printf(sio_str, "+SIO"); + furi_string_cat_printf(credential_str, " +SIO"); } } @@ -70,13 +69,10 @@ void picopass_scene_device_info_on_enter(void* context) { AlignCenter, FontSecondary, furi_string_get_cstr(credential_str)); - widget_add_string_element( - widget, 64, 46, AlignCenter, AlignCenter, FontSecondary, furi_string_get_cstr(sio_str)); furi_string_free(csn_str); furi_string_free(credential_str); furi_string_free(wiegand_str); - furi_string_free(sio_str); widget_add_button_element( picopass->widget, diff --git a/applications/external/picopass/scenes/picopass_scene_key_input.c b/applications/external/picopass/scenes/picopass_scene_key_input.c new file mode 100644 index 000000000..97db46653 --- /dev/null +++ b/applications/external/picopass/scenes/picopass_scene_key_input.c @@ -0,0 +1,48 @@ +#include "../picopass_i.h" +#include +#include +#include + +void picopass_scene_key_input_text_input_callback(void* context) { + Picopass* picopass = context; + + picopass->dev->dev_data.pacs.elite_kdf = true; + memcpy(picopass->dev->dev_data.pacs.key, picopass->byte_input_store, RFAL_PICOPASS_BLOCK_LEN); + view_dispatcher_send_custom_event(picopass->view_dispatcher, PicopassCustomEventByteInputDone); +} + +void picopass_scene_key_input_on_enter(void* context) { + Picopass* picopass = context; + + ByteInput* byte_input = picopass->byte_input; + byte_input_set_header_text(byte_input, "Enter The Key In Hex"); + byte_input_set_result_callback( + byte_input, + picopass_scene_key_input_text_input_callback, + NULL, + picopass, + picopass->byte_input_store, + RFAL_PICOPASS_BLOCK_LEN); + view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewByteInput); +} + +bool picopass_scene_key_input_on_event(void* context, SceneManagerEvent event) { + Picopass* picopass = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == PicopassCustomEventByteInputDone) { + scene_manager_next_scene(picopass->scene_manager, PicopassSceneWriteKey); + consumed = true; + } + } + return consumed; +} + +void picopass_scene_key_input_on_exit(void* context) { + Picopass* picopass = context; + + // Clear view + byte_input_set_result_callback(picopass->byte_input, NULL, NULL, NULL, NULL, 0); + byte_input_set_header_text(picopass->byte_input, ""); +} diff --git a/applications/external/picopass/scenes/picopass_scene_key_menu.c b/applications/external/picopass/scenes/picopass_scene_key_menu.c index 08adffed2..21d8a526d 100644 --- a/applications/external/picopass/scenes/picopass_scene_key_menu.c +++ b/applications/external/picopass/scenes/picopass_scene_key_menu.c @@ -6,7 +6,7 @@ enum SubmenuIndex { SubmenuIndexWriteiCE, SubmenuIndexWriteiCL, SubmenuIndexWriteiCS, - SubmenuIndexWriteCustom, //TODO: user input of key + SubmenuIndexWriteCustom, }; void picopass_scene_key_menu_submenu_callback(void* context, uint32_t index) { @@ -43,6 +43,12 @@ void picopass_scene_key_menu_on_enter(void* context) { SubmenuIndexWriteiCS, picopass_scene_key_menu_submenu_callback, picopass); + submenu_add_item( + submenu, + "Write Elite", + SubmenuIndexWriteCustom, + picopass_scene_key_menu_submenu_callback, + picopass); submenu_set_selected_item( picopass->submenu, @@ -84,6 +90,12 @@ bool picopass_scene_key_menu_on_event(void* context, SceneManagerEvent event) { picopass->dev->dev_data.pacs.elite_kdf = false; scene_manager_next_scene(picopass->scene_manager, PicopassSceneWriteKey); consumed = true; + } else if(event.event == SubmenuIndexWriteCustom) { + scene_manager_set_scene_state( + picopass->scene_manager, PicopassSceneKeyMenu, SubmenuIndexWriteCustom); + // Key and elite_kdf = true are both set in key_input scene + scene_manager_next_scene(picopass->scene_manager, PicopassSceneKeyInput); + consumed = true; } } else if(event.type == SceneManagerEventTypeBack) { consumed = scene_manager_search_and_switch_to_previous_scene( diff --git a/applications/external/picopass/scenes/picopass_scene_read_card_success.c b/applications/external/picopass/scenes/picopass_scene_read_card_success.c index 2f80cd7b9..adcdaded3 100644 --- a/applications/external/picopass/scenes/picopass_scene_read_card_success.c +++ b/applications/external/picopass/scenes/picopass_scene_read_card_success.c @@ -19,7 +19,7 @@ void picopass_scene_read_card_success_on_enter(void* context) { FuriString* csn_str = furi_string_alloc_set("CSN:"); FuriString* credential_str = furi_string_alloc(); FuriString* wiegand_str = furi_string_alloc(); - FuriString* sio_str = furi_string_alloc(); + FuriString* key_str = furi_string_alloc(); dolphin_deed(DolphinDeedNfcReadSuccess); @@ -79,7 +79,7 @@ void picopass_scene_read_card_success_on_enter(void* context) { size_t bytesLength = 1 + pacs->record.bitLength / 8; furi_string_set(credential_str, ""); for(uint8_t i = RFAL_PICOPASS_BLOCK_LEN - bytesLength; i < RFAL_PICOPASS_BLOCK_LEN; i++) { - furi_string_cat_printf(credential_str, " %02X", pacs->credential[i]); + furi_string_cat_printf(credential_str, "%02X", pacs->credential[i]); } if(pacs->record.valid) { @@ -90,19 +90,16 @@ void picopass_scene_read_card_success_on_enter(void* context) { } if(pacs->sio) { - furi_string_cat_printf(sio_str, "+SIO"); + furi_string_cat_printf(credential_str, " +SIO"); } if(pacs->key) { - if(pacs->sio) { - furi_string_cat_printf(sio_str, " "); - } - furi_string_cat_printf(sio_str, "Key: "); + furi_string_cat_printf(key_str, "Key: "); uint8_t key[RFAL_PICOPASS_BLOCK_LEN]; memcpy(key, &pacs->key, RFAL_PICOPASS_BLOCK_LEN); for(uint8_t i = 0; i < RFAL_PICOPASS_BLOCK_LEN; i++) { - furi_string_cat_printf(sio_str, "%02X", key[i]); + furi_string_cat_printf(key_str, "%02X", key[i]); } } @@ -134,12 +131,12 @@ void picopass_scene_read_card_success_on_enter(void* context) { FontSecondary, furi_string_get_cstr(credential_str)); widget_add_string_element( - widget, 64, 46, AlignCenter, AlignCenter, FontSecondary, furi_string_get_cstr(sio_str)); + widget, 64, 46, AlignCenter, AlignCenter, FontSecondary, furi_string_get_cstr(key_str)); furi_string_free(csn_str); furi_string_free(credential_str); furi_string_free(wiegand_str); - furi_string_free(sio_str); + furi_string_free(key_str); view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewWidget); } diff --git a/applications/external/picopass/scenes/picopass_scene_save_name.c b/applications/external/picopass/scenes/picopass_scene_save_name.c index baf882b80..a80932f08 100644 --- a/applications/external/picopass/scenes/picopass_scene_save_name.c +++ b/applications/external/picopass/scenes/picopass_scene_save_name.c @@ -52,8 +52,9 @@ bool picopass_scene_save_name_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == PicopassCustomEventTextInputDone) { + // Delete old file if renaming if(strcmp(picopass->dev->dev_name, "") != 0) { - // picopass_device_delete(picopass->dev, true); + picopass_device_delete(picopass->dev, true); } strlcpy( picopass->dev->dev_name, picopass->text_store, strlen(picopass->text_store) + 1); diff --git a/applications/external/picopass/scenes/picopass_scene_saved_menu.c b/applications/external/picopass/scenes/picopass_scene_saved_menu.c index 401f43f9b..0283906f2 100644 --- a/applications/external/picopass/scenes/picopass_scene_saved_menu.c +++ b/applications/external/picopass/scenes/picopass_scene_saved_menu.c @@ -5,6 +5,7 @@ enum SubmenuIndex { SubmenuIndexInfo, SubmenuIndexWrite, SubmenuIndexEmulate, + SubmenuIndexRename, }; void picopass_scene_saved_menu_submenu_callback(void* context, uint32_t index) { @@ -17,12 +18,6 @@ void picopass_scene_saved_menu_on_enter(void* context) { Picopass* picopass = context; Submenu* submenu = picopass->submenu; - submenu_add_item( - submenu, - "Delete", - SubmenuIndexDelete, - picopass_scene_saved_menu_submenu_callback, - picopass); submenu_add_item( submenu, "Info", SubmenuIndexInfo, picopass_scene_saved_menu_submenu_callback, picopass); submenu_add_item( @@ -33,6 +28,18 @@ void picopass_scene_saved_menu_on_enter(void* context) { SubmenuIndexEmulate, picopass_scene_saved_menu_submenu_callback, picopass); + submenu_add_item( + submenu, + "Rename", + SubmenuIndexRename, + picopass_scene_saved_menu_submenu_callback, + picopass); + submenu_add_item( + submenu, + "Delete", + SubmenuIndexDelete, + picopass_scene_saved_menu_submenu_callback, + picopass); submenu_set_selected_item( picopass->submenu, @@ -61,6 +68,9 @@ bool picopass_scene_saved_menu_on_event(void* context, SceneManagerEvent event) } else if(event.event == SubmenuIndexEmulate) { scene_manager_next_scene(picopass->scene_manager, PicopassSceneEmulate); consumed = true; + } else if(event.event == SubmenuIndexRename) { + scene_manager_next_scene(picopass->scene_manager, PicopassSceneSaveName); + consumed = true; } } diff --git a/applications/external/picopass/scenes/picopass_scene_start.c b/applications/external/picopass/scenes/picopass_scene_start.c index cfd758ed5..d6b394b3f 100644 --- a/applications/external/picopass/scenes/picopass_scene_start.c +++ b/applications/external/picopass/scenes/picopass_scene_start.c @@ -58,7 +58,7 @@ bool picopass_scene_start_on_event(void* context, SceneManagerEvent event) { consumed = true; } else if(event.event == SubmenuIndexLoclass) { scene_manager_set_scene_state( - picopass->scene_manager, PicopassSceneLoclass, PicopassSceneLoclass); + picopass->scene_manager, PicopassSceneStart, PicopassSceneLoclass); scene_manager_next_scene(picopass->scene_manager, PicopassSceneLoclass); consumed = true; } diff --git a/applications/external/picopass/scenes/picopass_scene_write_card.c b/applications/external/picopass/scenes/picopass_scene_write_card.c index ce396fc10..3c6eae296 100644 --- a/applications/external/picopass/scenes/picopass_scene_write_card.c +++ b/applications/external/picopass/scenes/picopass_scene_write_card.c @@ -4,7 +4,7 @@ void picopass_write_card_worker_callback(PicopassWorkerEvent event, void* context) { UNUSED(event); Picopass* picopass = context; - view_dispatcher_send_custom_event(picopass->view_dispatcher, PicopassCustomEventWorkerExit); + view_dispatcher_send_custom_event(picopass->view_dispatcher, event); } void picopass_scene_write_card_on_enter(void* context) { @@ -33,7 +33,10 @@ bool picopass_scene_write_card_on_event(void* context, SceneManagerEvent event) bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { - if(event.event == PicopassCustomEventWorkerExit) { + if(event.event == PicopassWorkerEventFail) { + scene_manager_next_scene(picopass->scene_manager, PicopassSceneWriteCardFailure); + consumed = true; + } else if(event.event == PicopassWorkerEventSuccess) { scene_manager_next_scene(picopass->scene_manager, PicopassSceneWriteCardSuccess); consumed = true; } diff --git a/applications/external/picopass/scenes/picopass_scene_write_card_failure.c b/applications/external/picopass/scenes/picopass_scene_write_card_failure.c new file mode 100644 index 000000000..4aae21996 --- /dev/null +++ b/applications/external/picopass/scenes/picopass_scene_write_card_failure.c @@ -0,0 +1,65 @@ +#include "../picopass_i.h" +#include + +void picopass_scene_write_card_failure_widget_callback( + GuiButtonType result, + InputType type, + void* context) { + furi_assert(context); + Picopass* picopass = context; + + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(picopass->view_dispatcher, result); + } +} + +void picopass_scene_write_card_failure_on_enter(void* context) { + Picopass* picopass = context; + Widget* widget = picopass->widget; + FuriString* str = furi_string_alloc_set("Write Failure!"); + + widget_add_button_element( + widget, + GuiButtonTypeLeft, + "Retry", + picopass_scene_write_card_failure_widget_callback, + picopass); + + widget_add_button_element( + widget, + GuiButtonTypeRight, + "Menu", + picopass_scene_write_card_failure_widget_callback, + picopass); + + widget_add_string_element( + widget, 64, 5, AlignCenter, AlignCenter, FontSecondary, furi_string_get_cstr(str)); + + furi_string_free(str); + + view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewWidget); +} + +bool picopass_scene_write_card_failure_on_event(void* context, SceneManagerEvent event) { + Picopass* picopass = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == GuiButtonTypeLeft) { + consumed = scene_manager_previous_scene(picopass->scene_manager); + } else if(event.event == GuiButtonTypeRight) { + // Clear device name + picopass_device_set_name(picopass->dev, ""); + consumed = scene_manager_search_and_switch_to_previous_scene( + picopass->scene_manager, PicopassSceneStart); + } + } + return consumed; +} + +void picopass_scene_write_card_failure_on_exit(void* context) { + Picopass* picopass = context; + + // Clear view + widget_reset(picopass->widget); +} diff --git a/applications/external/picopass/scenes/picopass_scene_write_card_success.c b/applications/external/picopass/scenes/picopass_scene_write_card_success.c index cd760272f..52b403cfe 100644 --- a/applications/external/picopass/scenes/picopass_scene_write_card_success.c +++ b/applications/external/picopass/scenes/picopass_scene_write_card_success.c @@ -55,8 +55,8 @@ bool picopass_scene_write_card_success_on_event(void* context, SceneManagerEvent } else if(event.event == GuiButtonTypeRight) { // Clear device name picopass_device_set_name(picopass->dev, ""); - scene_manager_next_scene(picopass->scene_manager, PicopassSceneCardMenu); - consumed = true; + consumed = scene_manager_search_and_switch_to_previous_scene( + picopass->scene_manager, PicopassSceneStart); } } return consumed; diff --git a/applications/external/pocsag_pager/application.fam b/applications/external/pocsag_pager/application.fam index cb893f66f..04634c81f 100644 --- a/applications/external/pocsag_pager/application.fam +++ b/applications/external/pocsag_pager/application.fam @@ -5,7 +5,6 @@ App( entry_point="pocsag_pager_app", requires=["gui"], stack_size=4 * 1024, - order=50, fap_icon="pocsag_pager_10px.png", fap_category="Sub-GHz", fap_icon_assets="images", diff --git a/applications/external/pocsag_pager/pocsag_pager_app_i.c b/applications/external/pocsag_pager/pocsag_pager_app_i.c index 88c3a8c30..8dda1d8b6 100644 --- a/applications/external/pocsag_pager/pocsag_pager_app_i.c +++ b/applications/external/pocsag_pager/pocsag_pager_app_i.c @@ -136,7 +136,7 @@ void pcsg_hopper_update(POCSAGPagerApp* app) { if(app->txrx->txrx_state == PCSGTxRxStateRx) { pcsg_rx_end(app); - } + }; if(app->txrx->txrx_state == PCSGTxRxStateIDLE) { subghz_receiver_reset(app->txrx->receiver); app->txrx->preset->frequency = diff --git a/applications/external/pocsag_pager/scenes/pocsag_pager_receiver.c b/applications/external/pocsag_pager/scenes/pocsag_pager_receiver.c index 58af9a64a..cc2abd7e0 100644 --- a/applications/external/pocsag_pager/scenes/pocsag_pager_receiver.c +++ b/applications/external/pocsag_pager/scenes/pocsag_pager_receiver.c @@ -135,7 +135,7 @@ void pocsag_pager_scene_receiver_on_enter(void* context) { if(app->txrx->txrx_state == PCSGTxRxStateRx) { pcsg_rx_end(app); - } + }; if((app->txrx->txrx_state == PCSGTxRxStateIDLE) || (app->txrx->txrx_state == PCSGTxRxStateSleep)) { // Start RX @@ -161,7 +161,7 @@ bool pocsag_pager_scene_receiver_on_event(void* context, SceneManagerEvent event if(app->txrx->txrx_state == PCSGTxRxStateRx) { pcsg_rx_end(app); pcsg_idle(app); - } + }; app->txrx->hopper_state = PCSGHopperStateOFF; app->txrx->idx_menu_chosen = 0; subghz_receiver_set_rx_callback(app->txrx->receiver, NULL, app); diff --git a/applications/external/pocsag_pager/views/pocsag_pager_receiver.c b/applications/external/pocsag_pager/views/pocsag_pager_receiver.c index 755102682..629c3894e 100644 --- a/applications/external/pocsag_pager/views/pocsag_pager_receiver.c +++ b/applications/external/pocsag_pager/views/pocsag_pager_receiver.c @@ -1,6 +1,6 @@ #include "pocsag_pager_receiver.h" #include "../pocsag_pager_app_i.h" -#include +#include "pocsag_pager_icons.h" #include #include diff --git a/applications/external/pomodoro/flipp_pomodoro_app.c b/applications/external/pomodoro/flipp_pomodoro_app.c index c49952c87..c91edc93c 100644 --- a/applications/external/pomodoro/flipp_pomodoro_app.c +++ b/applications/external/pomodoro/flipp_pomodoro_app.c @@ -32,6 +32,10 @@ static bool flipp_pomodoro_app_custom_event_callback(void* ctx, uint32_t event) return CustomEventConsumed; case FlippPomodoroAppCustomEventStageComplete: if(flipp_pomodoro__get_stage(app->state) == FlippPomodoroStageFocus) { + // REGISTER a deed on work stage complete to get an acheivement + dolphin_deed(DolphinDeedPluginGameWin); + FURI_LOG_I(TAG, "Focus stage reward added"); + flipp_pomodoro_statistics__increase_focus_stages_completed(app->statistics); }; @@ -106,9 +110,12 @@ int32_t flipp_pomodoro_app(void* p) { FURI_LOG_I(TAG, "Initial"); FlippPomodoroApp* app = flipp_pomodoro_app_alloc(); + FURI_LOG_I(TAG, "Run deed added"); + dolphin_deed(DolphinDeedPluginGameStart); + view_dispatcher_run(app->view_dispatcher); flipp_pomodoro_app_free(app); return 0; -}; +}; \ No newline at end of file diff --git a/applications/external/pomodoro/flipp_pomodoro_app_i.h b/applications/external/pomodoro/flipp_pomodoro_app_i.h index 56d8a6133..8b8650776 100644 --- a/applications/external/pomodoro/flipp_pomodoro_app_i.h +++ b/applications/external/pomodoro/flipp_pomodoro_app_i.h @@ -15,6 +15,7 @@ #include #include #include +#include #include // App resource imports diff --git a/applications/external/protoview/application.fam b/applications/external/protoview/application.fam index 7dbb7ea31..75084b852 100644 --- a/applications/external/protoview/application.fam +++ b/applications/external/protoview/application.fam @@ -5,7 +5,6 @@ App( entry_point="protoview_app_entry", requires=["gui"], stack_size=8 * 1024, - order=50, fap_icon="appicon.png", fap_category="Sub-GHz", fap_author="@antirez & (fixes by @xMasterX)", diff --git a/applications/external/protoview/signal_file.c b/applications/external/protoview/signal_file.c index e7934d04b..8f325ab52 100644 --- a/applications/external/protoview/signal_file.c +++ b/applications/external/protoview/signal_file.c @@ -45,14 +45,21 @@ bool save_signal(ProtoViewApp* app, const char* filename) { custom, "Custom_preset_module: CC1101\n" "Custom_preset_data: "); - for(int j = 0; regs[j]; j += 2) { + + /* We will know the size of the preset data once we reach the end + * of the registers (null address). For now it's INT_MAX. */ + int preset_data_size = INT_MAX; + bool patable_reached = false; + for(int j = 0; j <= preset_data_size; j += 2) { + // End reached, set the size to write the remaining 8 bytes (PATABLE) + if(!patable_reached && regs[j] == 0) { + preset_data_size = j + 8; + patable_reached = true; + } furi_string_cat_printf(custom, "%02X %02X ", (int)regs[j], (int)regs[j + 1]); } - // Add patable - furi_string_cat(custom, "00 00 C0 00 00 00 00 00 00 00 "); - //size_t len = furi_string_size(file_content); - //furi_string_set_char(custom, len - 1, '\n'); - furi_string_cat(custom, "\n"); + size_t len = furi_string_size(custom); + furi_string_set_char(custom, len - 1, '\n'); furi_string_cat(file_content, custom); furi_string_free(custom); } diff --git a/applications/external/rc2014_coleco/application.fam b/applications/external/rc2014_coleco/application.fam index fe3ee028b..d9b3aa727 100644 --- a/applications/external/rc2014_coleco/application.fam +++ b/applications/external/rc2014_coleco/application.fam @@ -6,7 +6,6 @@ App( cdefines=["APP_COLECO"], requires=["gui"], stack_size=1 * 1024, - order=35, fap_icon="coleco_10px.png", fap_icon_assets="icons", fap_category="GPIO", diff --git a/applications/external/reversi/application.fam b/applications/external/reversi/application.fam index 25a087c0c..87091e91a 100644 --- a/applications/external/reversi/application.fam +++ b/applications/external/reversi/application.fam @@ -8,7 +8,6 @@ App( "gui", ], stack_size=1 * 1024, - order=90, fap_icon="game_reversi.png", fap_category="Games", fap_icon_assets_symbol="game_reversi", diff --git a/applications/external/rootoflife/application.fam b/applications/external/rootoflife/application.fam index aa3d68211..c335f77aa 100644 --- a/applications/external/rootoflife/application.fam +++ b/applications/external/rootoflife/application.fam @@ -6,7 +6,6 @@ App( cdefines=["APP_ROOTS_OF_LIFE_GAME"], requires=["gui"], stack_size=1 * 1024, - order=30, fap_icon="roots_of_life_10px.png", fap_category="Games", fap_icon_assets="images", diff --git a/applications/external/sam/application.fam b/applications/external/sam/application.fam index 8a6d70c07..e123f455b 100644 --- a/applications/external/sam/application.fam +++ b/applications/external/sam/application.fam @@ -8,7 +8,6 @@ App( "dialogs", ], stack_size=4 * 1024, - order=20, fap_icon="music_10px.png", fap_category="Media", ) @@ -22,7 +21,6 @@ App( "dialogs", ], stack_size=4 * 1024, - order=20, fap_icon="music_10px.png", fap_category="Media", ) @@ -36,7 +34,6 @@ App( "dialogs", ], stack_size=4 * 1024, - order=20, fap_icon="music_10px.png", fap_category="Media", ) @@ -50,7 +47,6 @@ App( "dialogs", ], stack_size=4 * 1024, - order=20, fap_icon="music_10px.png", fap_category="Media", ) diff --git a/applications/external/scorched_tanks/application.fam b/applications/external/scorched_tanks/application.fam index 4d74c5ced..6256a3c47 100644 --- a/applications/external/scorched_tanks/application.fam +++ b/applications/external/scorched_tanks/application.fam @@ -6,7 +6,6 @@ App( cdefines=["APP_SCORCHED_TANKS_GAME"], requires=["gui"], stack_size=1 * 1024, - order=100, fap_icon="scorchedTanks_10px.png", fap_category="Games", fap_author="@jasniec", diff --git a/applications/external/sentry_safe/application.fam b/applications/external/sentry_safe/application.fam index 73264cf01..7f17ca5f6 100644 --- a/applications/external/sentry_safe/application.fam +++ b/applications/external/sentry_safe/application.fam @@ -5,7 +5,6 @@ App( entry_point="sentry_safe_app", requires=["gui"], stack_size=1 * 1024, - order=40, fap_icon="safe_10px.png", fap_category="GPIO", fap_author="@H4ckd4ddy & @xMasterX (ported to latest firmware)", diff --git a/applications/external/sentry_safe/sentry_safe.c b/applications/external/sentry_safe/sentry_safe.c index d9c75d1ea..789b43f2c 100644 --- a/applications/external/sentry_safe/sentry_safe.c +++ b/applications/external/sentry_safe/sentry_safe.c @@ -166,4 +166,4 @@ int32_t sentry_safe_app(void* p) { free(sentry_state); return 0; -} +} \ No newline at end of file diff --git a/applications/external/signal_generator/application.fam b/applications/external/signal_generator/application.fam index a7b93b817..4a5877a7c 100644 --- a/applications/external/signal_generator/application.fam +++ b/applications/external/signal_generator/application.fam @@ -5,7 +5,9 @@ App( entry_point="signal_gen_app", requires=["gui"], stack_size=1 * 1024, - order=50, + fap_description="Control GPIO pins to generate digital signals", + fap_version="1.0", fap_icon="signal_gen_10px.png", fap_category="GPIO", + fap_icon_assets="icons", ) diff --git a/applications/external/signal_generator/views/signal_gen_pwm.c b/applications/external/signal_generator/views/signal_gen_pwm.c index 84dc63f92..63669a937 100644 --- a/applications/external/signal_generator/views/signal_gen_pwm.c +++ b/applications/external/signal_generator/views/signal_gen_pwm.c @@ -1,6 +1,7 @@ #include "../signal_gen_app_i.h" #include #include +#include "signal_generator_icons.h" #include typedef enum { diff --git a/applications/external/slots/application.fam b/applications/external/slots/application.fam index 190841543..9a2e244d8 100644 --- a/applications/external/slots/application.fam +++ b/applications/external/slots/application.fam @@ -7,7 +7,6 @@ App( requires=["gui"], stack_size=1 * 1024, fap_icon="ddgame_icon.png", - order=30, fap_category="Games", fap_icon_assets="assets", fap_author="@Daniel-dev-s", diff --git a/applications/external/snake_2/application.fam b/applications/external/snake_2/application.fam index 287522983..f05f76441 100644 --- a/applications/external/snake_2/application.fam +++ b/applications/external/snake_2/application.fam @@ -6,7 +6,6 @@ App( cdefines=["APP_SNAKE_20"], requires=["gui"], stack_size=1 * 1024, - order=30, fap_icon="snake_10px.png", fap_category="Games", fap_author="@Willzvul", diff --git a/applications/external/snake_2/snake_20.c b/applications/external/snake_2/snake_20.c index ee6ae68f3..c45c9796c 100644 --- a/applications/external/snake_2/snake_20.c +++ b/applications/external/snake_2/snake_20.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -399,6 +400,8 @@ int32_t snake_20_app(void* p) { 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); @@ -522,4 +525,4 @@ int32_t snake_20_app(void* p) { free(snake_state); return 0; -} +} \ No newline at end of file diff --git a/applications/external/solitaire/LICENSE b/applications/external/solitaire/LICENSE new file mode 100644 index 000000000..37558e682 --- /dev/null +++ b/applications/external/solitaire/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Tibor Tálosi + +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/solitaire/application.fam b/applications/external/solitaire/application.fam index 99067e1b9..9394dfc8a 100644 --- a/applications/external/solitaire/application.fam +++ b/applications/external/solitaire/application.fam @@ -5,7 +5,6 @@ App( entry_point="solitaire_app", requires=["gui", "storage", "canvas"], stack_size=2 * 1024, - order=30, fap_icon="solitaire_10px.png", fap_category="Games", fap_icon_assets="assets", diff --git a/applications/external/solitaire/defines.h b/applications/external/solitaire/defines.h index 8734395e8..a225b7c83 100644 --- a/applications/external/solitaire/defines.h +++ b/applications/external/solitaire/defines.h @@ -44,6 +44,7 @@ typedef struct { InputKey input; bool started; + bool had_change; bool processing; bool longPress; PlayState state; diff --git a/applications/external/solitaire/solitaire.c b/applications/external/solitaire/solitaire.c index 82506384e..9b9c8ce74 100644 --- a/applications/external/solitaire/solitaire.c +++ b/applications/external/solitaire/solitaire.c @@ -1,12 +1,15 @@ #include +#include #include #include #include "defines.h" #include "common/ui.h" #include "solitaire_icons.h" +#include #include #include void init(GameState* game_state); + const NotificationSequence sequence_fail = { &message_vibro_on, &message_note_c4, @@ -33,13 +36,6 @@ int8_t columns[7][3] = { }; bool can_place_card(Card where, Card what) { - FURI_LOG_D( - APP_NAME, - "TESTING pip %i, letter %i with pip %i, letter %i", - where.pip, - where.character, - what.pip, - what.character); bool a_black = where.pip == 0 || where.pip == 3; bool b_black = what.pip == 0 || what.pip == 3; if(a_black == b_black) return false; @@ -53,86 +49,97 @@ bool can_place_card(Card where, Card what) { } static void draw_scene(Canvas* const canvas, const GameState* game_state) { - int deckIndex = game_state->deck.index; - if(game_state->dragging_deck) deckIndex--; + if(game_state->had_change) { + int deckIndex = game_state->deck.index; + if(game_state->dragging_deck) deckIndex--; - if((game_state->deck.index < (game_state->deck.card_count - 1) || - game_state->deck.index == -1) && - game_state->deck.card_count > 0) { - draw_card_back_at(columns[0][0], columns[0][1], canvas); - if(game_state->selectRow == 0 && game_state->selectColumn == 0) { - draw_rounded_box( - canvas, - columns[0][0] + 1, - columns[0][1] + 1, - CARD_WIDTH - 2, - CARD_HEIGHT - 2, - Inverse); - } - } else - draw_card_space( - columns[0][0], - columns[0][1], - game_state->selectRow == 0 && game_state->selectColumn == 0, - canvas); - //deck side - if(deckIndex >= 0) { - Card c = game_state->deck.cards[deckIndex]; - draw_card_at_colored( - columns[1][0], - columns[1][1], - c.pip, - c.character, - game_state->selectRow == 0 && game_state->selectColumn == 1, - canvas); - } else - draw_card_space( - columns[1][0], - columns[1][1], - game_state->selectRow == 0 && game_state->selectColumn == 1, - canvas); - - for(uint8_t i = 0; i < 4; i++) { - Card current = game_state->top_cards[i]; - bool selected = game_state->selectRow == 0 && game_state->selectColumn == (i + 3); - if(current.disabled) { - draw_card_space(columns[i + 3][0], columns[i + 3][1], selected, canvas); - } else { - draw_card_at( - columns[i + 3][0], columns[i + 3][1], current.pip, current.character, canvas); - if(selected) { + if((game_state->deck.index < (game_state->deck.card_count - 1) || + game_state->deck.index == -1) && + game_state->deck.card_count > 0) { + draw_card_back_at(columns[0][0], columns[0][1], canvas); + if(game_state->selectRow == 0 && game_state->selectColumn == 0) { draw_rounded_box( - canvas, columns[i + 3][0], columns[i + 3][1], CARD_WIDTH, CARD_HEIGHT, Inverse); + canvas, + columns[0][0] + 1, + columns[0][1] + 1, + CARD_WIDTH - 2, + CARD_HEIGHT - 2, + Inverse); + } + } else + draw_card_space( + columns[0][0], + columns[0][1], + game_state->selectRow == 0 && game_state->selectColumn == 0, + canvas); + //deck side + if(deckIndex >= 0) { + Card c = game_state->deck.cards[deckIndex]; + draw_card_at_colored( + columns[1][0], + columns[1][1], + c.pip, + c.character, + game_state->selectRow == 0 && game_state->selectColumn == 1, + canvas); + } else + draw_card_space( + columns[1][0], + columns[1][1], + game_state->selectRow == 0 && game_state->selectColumn == 1, + canvas); + + for(uint8_t i = 0; i < 4; i++) { + Card current = game_state->top_cards[i]; + bool selected = game_state->selectRow == 0 && game_state->selectColumn == (i + 3); + if(current.disabled) { + draw_card_space(columns[i + 3][0], columns[i + 3][1], selected, canvas); + } else { + draw_card_at( + columns[i + 3][0], columns[i + 3][1], current.pip, current.character, canvas); + if(selected) { + draw_rounded_box( + canvas, + columns[i + 3][0], + columns[i + 3][1], + CARD_WIDTH, + CARD_HEIGHT, + Inverse); + } } } - } - for(uint8_t i = 0; i < 7; i++) { - bool selected = game_state->selectRow == 1 && game_state->selectColumn == i; - int8_t index = (game_state->bottom_columns[i].index - 1 - game_state->selected_card); - if(index < 0) index = 0; - draw_hand_column( - game_state->bottom_columns[i], - columns[i][0], - columns[i][2], - selected ? index : -1, - canvas); - } + for(uint8_t i = 0; i < 7; i++) { + bool selected = game_state->selectRow == 1 && game_state->selectColumn == i; + int8_t index = (game_state->bottom_columns[i].index - 1 - game_state->selected_card); + if(index < 0) index = 0; + draw_hand_column( + game_state->bottom_columns[i], + columns[i][0], + columns[i][2], + selected ? index : -1, + canvas); + } - int8_t pos[2] = { - columns[game_state->selectColumn][0], - columns[game_state->selectColumn][game_state->selectRow + 1]}; + int8_t pos[2] = { + columns[game_state->selectColumn][0], + columns[game_state->selectColumn][game_state->selectRow + 1]}; - /* draw_icon_clip(canvas, &I_card_graphics, pos[0] + CARD_HALF_WIDTH, pos[1] + CARD_HALF_HEIGHT, 30, 5, 5, 5, - Filled);*/ + /* draw_icon_clip(canvas, &I_card_graphics, pos[0] + CARD_HALF_WIDTH, pos[1] + CARD_HALF_HEIGHT, 30, 5, 5, 5, + Filled);*/ - if(game_state->dragging_hand.index > 0) { - draw_hand_column( - game_state->dragging_hand, - pos[0] + CARD_HALF_WIDTH + 3, - pos[1] + CARD_HALF_HEIGHT + 3, - -1, - canvas); + if(game_state->dragging_hand.index > 0) { + draw_hand_column( + game_state->dragging_hand, + pos[0] + CARD_HALF_WIDTH + 3, + pos[1] + CARD_HALF_HEIGHT + 3, + -1, + canvas); + } + + clone_buffer(get_buffer(canvas), game_state->animation.buffer); + } else { + clone_buffer(game_state->animation.buffer, get_buffer(canvas)); } } @@ -154,9 +161,11 @@ static void draw_animation(Canvas* const canvas, const GameState* game_state) { } static void render_callback(Canvas* const canvas, void* ctx) { - furi_assert(ctx); const GameState* game_state = ctx; - furi_mutex_acquire(game_state->mutex, FuriWaitForever); + furi_mutex_acquire(game_state->mutex, 25); + if(game_state == NULL) { + return; + } switch(game_state->state) { case GameStateAnimate: @@ -253,7 +262,6 @@ bool place_on_top(Card* where, Card what) { int8_t b_letter = (int8_t)what.character; if(a_letter == 12) a_letter = -1; if(b_letter == 12) b_letter = -1; - if(where->disabled && b_letter != -1) return false; if((a_letter + 1) == b_letter) { @@ -276,6 +284,9 @@ void tick(GameState* game_state, NotificationApp* notification) { if(game_state->top_cards[0].character == 11 && game_state->top_cards[1].character == 11 && game_state->top_cards[2].character == 11 && game_state->top_cards[3].character == 11) { game_state->state = GameStateAnimate; + game_state->had_change = true; + dolphin_deed(DolphinDeedPluginGameWin); + return; } } @@ -406,6 +417,7 @@ void tick(GameState* game_state, NotificationApp* notification) { } void init(GameState* game_state) { + dolphin_deed(DolphinDeedPluginGameStart); game_state->selectColumn = 0; game_state->selected_card = 0; game_state->selectRow = 0; @@ -484,16 +496,17 @@ int32_t solitaire_app(void* p) { FuriTimer* timer = furi_timer_alloc(update_timer_callback, FuriTimerTypePeriodic, event_queue); furi_timer_start(timer, furi_kernel_get_tick_frequency() / 30); - Gui* gui = furi_record_open(RECORD_GUI); + Gui* gui = furi_record_open("gui"); gui_add_view_port(gui, view_port, GuiLayerFullscreen); AppEvent event; - for(bool processing = true; processing;) { FuriStatus event_status = furi_message_queue_get(event_queue, &event, 150); furi_mutex_acquire(game_state->mutex, FuriWaitForever); + game_state->had_change = false; if(event_status == FuriStatusOk) { if(event.type == EventTypeKey) { + game_state->had_change = true; if(event.input.type == InputTypeLong) { game_state->longPress = true; switch(event.input.key) { @@ -540,6 +553,7 @@ int32_t solitaire_app(void* p) { game_state->input = InputKeyMAX; } } + view_port_update(view_port); furi_mutex_release(game_state->mutex); } @@ -561,5 +575,6 @@ free_and_exit: free(game_state->deck.cards); free(game_state); furi_message_queue_free(event_queue); + return return_code; -} +} \ No newline at end of file diff --git a/applications/external/spectrum_analyzer/application.fam b/applications/external/spectrum_analyzer/application.fam index 27cc286d9..13f5d49f9 100644 --- a/applications/external/spectrum_analyzer/application.fam +++ b/applications/external/spectrum_analyzer/application.fam @@ -5,7 +5,6 @@ App( entry_point="spectrum_analyzer_app", requires=["gui"], stack_size=2 * 1024, - order=12, fap_icon="spectrum_10px.png", fap_category="Sub-GHz", fap_author="@xMasterX & @theY4Kman & @ALEEF02 (original by @jolcese)", diff --git a/applications/external/spectrum_analyzer/spectrum_analyzer.c b/applications/external/spectrum_analyzer/spectrum_analyzer.c index ed6e86867..345dd008b 100644 --- a/applications/external/spectrum_analyzer/spectrum_analyzer.c +++ b/applications/external/spectrum_analyzer/spectrum_analyzer.c @@ -608,4 +608,4 @@ int32_t spectrum_analyzer_app(void* p) { spectrum_analyzer_free(spectrum_analyzer); return 0; -} +} \ No newline at end of file diff --git a/applications/external/spi_mem_manager/application.fam b/applications/external/spi_mem_manager/application.fam index a21f8061d..8d1100cf9 100644 --- a/applications/external/spi_mem_manager/application.fam +++ b/applications/external/spi_mem_manager/application.fam @@ -5,7 +5,8 @@ App( entry_point="spi_mem_app", requires=["gui"], stack_size=1 * 2048, - order=30, + fap_description="Application for reading and writing 25-series SPI memory chips", + fap_version="1.0", fap_icon="images/Dip8_10px.png", fap_category="GPIO", fap_icon_assets="images", diff --git a/applications/external/spi_mem_manager/views/spi_mem_view_detect.c b/applications/external/spi_mem_manager/views/spi_mem_view_detect.c index eddf36e49..473d54ae2 100644 --- a/applications/external/spi_mem_manager/views/spi_mem_view_detect.c +++ b/applications/external/spi_mem_manager/views/spi_mem_view_detect.c @@ -1,5 +1,6 @@ #include "spi_mem_view_detect.h" #include "spi_mem_manager_icons.h" +#include #include struct SPIMemDetectView { diff --git a/applications/external/subghz_bruteforcer/application.fam b/applications/external/subghz_bruteforcer/application.fam index 713520a2c..bb9cd6d24 100644 --- a/applications/external/subghz_bruteforcer/application.fam +++ b/applications/external/subghz_bruteforcer/application.fam @@ -5,7 +5,6 @@ App( entry_point="subbrute_app", requires=["gui", "dialogs"], stack_size=2 * 1024, - order=11, fap_icon="subbrute_10px.png", fap_category="Sub-GHz", fap_icon_assets="images", diff --git a/applications/external/subghz_playlist/application.fam b/applications/external/subghz_playlist/application.fam index 8fe9ccbaf..5050197f2 100644 --- a/applications/external/subghz_playlist/application.fam +++ b/applications/external/subghz_playlist/application.fam @@ -5,9 +5,9 @@ App( entry_point="playlist_app", requires=["storage", "gui", "dialogs", "subghz"], stack_size=2 * 1024, - order=14, fap_icon="subplaylist_10px.png", fap_category="Sub-GHz", + fap_icon_assets="images", fap_author="@darmiel", fap_version="1.0", fap_description="App works with list of sub-ghz files from .txt file that contains paths to target files.", diff --git a/applications/external/subghz_playlist/playlist.c b/applications/external/subghz_playlist/playlist.c index fe0186e74..85b5109b8 100644 --- a/applications/external/subghz_playlist/playlist.c +++ b/applications/external/subghz_playlist/playlist.c @@ -6,6 +6,7 @@ #include #include +#include "subghz_playlist_icons.h" #include #include diff --git a/applications/external/subghz_remote/application.fam b/applications/external/subghz_remote/application.fam index 7eee1369f..1a99a2025 100644 --- a/applications/external/subghz_remote/application.fam +++ b/applications/external/subghz_remote/application.fam @@ -4,7 +4,6 @@ App( apptype=FlipperAppType.EXTERNAL, entry_point="subghz_remote_app", stack_size=2 * 1024, - order=11, fap_icon="icon.png", fap_description="SubGhz Remote, uses up to 5 .sub files", fap_category="Sub-GHz", diff --git a/applications/external/swd_probe/application.fam b/applications/external/swd_probe/application.fam index 8239121b1..998dcc7b6 100644 --- a/applications/external/swd_probe/application.fam +++ b/applications/external/swd_probe/application.fam @@ -5,7 +5,6 @@ App( entry_point="swd_probe_app_main", requires=["notification", "gui", "storage", "dialogs", "cli"], stack_size=2 * 1024, - order=10, fap_icon="icons/app.png", fap_category="GPIO", fap_icon_assets="icons", diff --git a/applications/external/swd_probe/swd_probe_app.c b/applications/external/swd_probe/swd_probe_app.c index ba4cbd1ee..b43b9c1c8 100644 --- a/applications/external/swd_probe/swd_probe_app.c +++ b/applications/external/swd_probe/swd_probe_app.c @@ -3137,6 +3137,8 @@ int32_t swd_probe_app_main(void* p) { DBGS("swd_execute_script"); swd_execute_script(app, SWD_PATH "/startup.swd"); + dolphin_deed(DolphinDeedPluginGameStart); + DBGS("processing"); for(bool processing = true; processing;) { swd_main_loop(app); diff --git a/applications/external/swd_probe/swd_probe_app.h b/applications/external/swd_probe/swd_probe_app.h index b60617e98..5a45a4fd9 100644 --- a/applications/external/swd_probe/swd_probe_app.h +++ b/applications/external/swd_probe/swd_probe_app.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -240,4 +241,4 @@ typedef struct { uint8_t swd_read_memory(AppFSM* const ctx, uint8_t ap, uint32_t address, uint32_t* data); -#endif +#endif \ No newline at end of file diff --git a/applications/external/t_rex_runner/application.fam b/applications/external/t_rex_runner/application.fam index 843ea307d..739a5bd07 100644 --- a/applications/external/t_rex_runner/application.fam +++ b/applications/external/t_rex_runner/application.fam @@ -9,7 +9,6 @@ App( fap_category="Games", fap_icon="trexrunner_icon.png", fap_icon_assets="assets", - order=36, fap_author="@Rrycbarm", fap_weburl="https://github.com/Rrycbarm/t-rex-runner", fap_version="1.2", diff --git a/applications/external/t_rex_runner/trexrunner.c b/applications/external/t_rex_runner/trexrunner.c index a1351a4ce..c676c407e 100644 --- a/applications/external/t_rex_runner/trexrunner.c +++ b/applications/external/t_rex_runner/trexrunner.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -22,7 +23,8 @@ #define CACTUS_W 10 #define CACTUS_H 10 -#define START_x_speed 25 +#define START_x_speed 35 +#define X_INCREASE 3 #define BACKGROUND_W 128 #define BACKGROUND_H 12 @@ -101,16 +103,23 @@ static void timer_callback(void* ctx) { // Update Cactus state if(game_state->has_cactus) { game_state->cactus_position = - game_state->cactus_position - game_state->x_speed * delta_time_ms / 1000; + game_state->cactus_position - (game_state->x_speed - 15) * delta_time_ms / 1000; if(game_state->cactus_position <= 0) { game_state->has_cactus = 0; game_state->score = game_state->score + 1; + + // Increase speed + game_state->x_speed = game_state->x_speed + X_INCREASE; } } - // Create cactus (not random) + // Create cactus (random frame in 1.5s) else { - game_state->has_cactus = 1; - game_state->cactus_position = 120; + uint8_t randomuint8[1]; + furi_hal_random_fill_buf(randomuint8, 1); + if(randomuint8[0] % 30 == 0) { + game_state->has_cactus = 1; + game_state->cactus_position = 120; + } } // Move horizontal line @@ -120,9 +129,9 @@ static void timer_callback(void* ctx) { game_state->background_position - game_state->x_speed * delta_time_ms / 1000; // Lose condition - if((game_state->y_position + 22 >= (64 - CACTUS_H)) && - ((DINO_START_X + 20) >= game_state->cactus_position) && - (DINO_START_X <= (game_state->cactus_position + CACTUS_W))) + if(game_state->has_cactus && ((game_state->y_position + 22 >= (64 - CACTUS_H)) && + ((DINO_START_X + 20) >= game_state->cactus_position) && + (DINO_START_X <= (game_state->cactus_position + CACTUS_W)))) game_state->lost = 1; furi_mutex_release(game_state->mutex); diff --git a/applications/external/tama_p1/application.fam b/applications/external/tama_p1/application.fam index e51281ff7..4152b054c 100644 --- a/applications/external/tama_p1/application.fam +++ b/applications/external/tama_p1/application.fam @@ -6,7 +6,6 @@ App( cdefines=["APP_TAMA_P1"], requires=["gui", "storage"], stack_size=2 * 1024, - order=215, fap_icon="tamaIcon.png", fap_category="Games", ) diff --git a/applications/external/tanksgame/application.fam b/applications/external/tanksgame/application.fam index f4fe49723..bf6bd1b4a 100644 --- a/applications/external/tanksgame/application.fam +++ b/applications/external/tanksgame/application.fam @@ -6,7 +6,6 @@ App( cdefines=["APP_TANKS_GAME"], requires=["gui", "subghz"], stack_size=4 * 1024, - order=730, fap_icon="tanksIcon.png", fap_category="Games", fap_icon_assets="images", diff --git a/applications/external/tetris_game/application.fam b/applications/external/tetris_game/application.fam index eb6ab5d5e..0766daf1e 100644 --- a/applications/external/tetris_game/application.fam +++ b/applications/external/tetris_game/application.fam @@ -5,7 +5,6 @@ App( entry_point="tetris_game_app", requires=["gui"], stack_size=2 * 1024, - order=240, fap_icon="tetris_10px.png", fap_category="Games", fap_author="@xMasterX & @jeffplang", diff --git a/applications/external/tetris_game/tetris_game.c b/applications/external/tetris_game/tetris_game.c index 653718fd4..07534d725 100644 --- a/applications/external/tetris_game/tetris_game.c +++ b/applications/external/tetris_game/tetris_game.c @@ -6,6 +6,7 @@ #include #include #include +#include #define BORDER_OFFSET 1 #define MARGIN_OFFSET 3 @@ -387,6 +388,9 @@ int32_t tetris_game_app() { Piece* newPiece = malloc(sizeof(Piece)); uint8_t downRepeatCounter = 0; + // Call dolphin deed on game start + dolphin_deed(DolphinDeedPluginGameStart); + for(bool processing = true; processing;) { // This 10U implicitly sets the game loop speed. downRepeatCounter relies on this value FuriStatus event_status = furi_message_queue_get(event_queue, &event, 10U); @@ -473,4 +477,4 @@ int32_t tetris_game_app() { free(tetris_state); return 0; -} +} \ No newline at end of file diff --git a/applications/external/text2sam/application.fam b/applications/external/text2sam/application.fam index 5598df644..3a0765680 100644 --- a/applications/external/text2sam/application.fam +++ b/applications/external/text2sam/application.fam @@ -13,7 +13,6 @@ App( # stack_size=2 * 1024, fap_icon="icon.png", fap_category="Media", - order=20, fap_author="@Round-Pi & (Fixes by @Willy-JL)", fap_weburl="https://github.com/Round-Pi/flipperzero-text2sam", fap_version="1.1", diff --git a/applications/external/text_viewer/application.fam b/applications/external/text_viewer/application.fam index 65100d9d8..6bdfe7c89 100644 --- a/applications/external/text_viewer/application.fam +++ b/applications/external/text_viewer/application.fam @@ -8,7 +8,6 @@ App( "dialogs", ], stack_size=10 * 1024, - order=20, fap_icon="icons/text_10px.png", fap_category="Tools", fap_icon_assets="icons", diff --git a/applications/external/tictactoe_game/application.fam b/applications/external/tictactoe_game/application.fam index 3def1fa85..48d904d0e 100644 --- a/applications/external/tictactoe_game/application.fam +++ b/applications/external/tictactoe_game/application.fam @@ -5,7 +5,6 @@ App( entry_point="tictactoe_game_app", requires=["gui"], stack_size=1 * 1024, - order=250, fap_icon="tictactoe_10px.png", fap_category="Games", fap_author="@xMasterX & @gotnull", diff --git a/applications/external/tictactoe_game/tictactoe_game.c b/applications/external/tictactoe_game/tictactoe_game.c index b6c0747d6..6ad076a4a 100644 --- a/applications/external/tictactoe_game/tictactoe_game.c +++ b/applications/external/tictactoe_game/tictactoe_game.c @@ -3,6 +3,7 @@ #include #include #include +#include #define TAG "TicTacToe" @@ -331,6 +332,9 @@ int32_t tictactoe_game_app(void* p) { Gui* gui = furi_record_open(RECORD_GUI); gui_add_view_port(gui, view_port, GuiLayerFullscreen); + // Call dolphin deed on game start + dolphin_deed(DolphinDeedPluginGameStart); + GameEvent event; for(bool processing = true; processing;) { FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); @@ -380,4 +384,4 @@ int32_t tictactoe_game_app(void* p) { free(tictactoe_state); return 0; -} +} \ No newline at end of file diff --git a/applications/external/timelapse/application.fam b/applications/external/timelapse/application.fam index 6dc6a3bc4..e59dc9722 100644 --- a/applications/external/timelapse/application.fam +++ b/applications/external/timelapse/application.fam @@ -6,7 +6,6 @@ App( cdefines=["APP_ZEITRAFFER"], requires=["gui", "input", "notification", "gpio"], stack_size=2 * 1024, - order=90, fap_icon_assets="icons", fap_icon="zeitraffer.png", fap_category="GPIO", diff --git a/applications/external/totp/application.fam b/applications/external/totp/application.fam index 729bc14fa..8e4eaa519 100644 --- a/applications/external/totp/application.fam +++ b/applications/external/totp/application.fam @@ -6,8 +6,7 @@ App( cdefines=["APP_TOTP"], requires=["gui", "cli", "dialogs", "storage", "input", "notification", "bt"], stack_size=2 * 1024, - order=20, - fap_version="4.01", + fap_version="4.03", fap_author="Alexander Kopachov (@akopachov)", fap_description="Software-based TOTP authenticator for Flipper Zero device", fap_weburl="https://github.com/akopachov/flipper-zero_authenticator", diff --git a/applications/external/totp/cli/cli.c b/applications/external/totp/cli/cli.c index 4cb68ce83..a556c31ac 100644 --- a/applications/external/totp/cli/cli.c +++ b/applications/external/totp/cli/cli.c @@ -47,7 +47,7 @@ static void totp_cli_handler(Cli* cli, FuriString* args, void* context) { } else if( furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_LIST) == 0 || furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_LIST_ALT) == 0) { - totp_cli_command_list_handle(plugin_state, cli); + totp_cli_command_list_handle(plugin_state, args, cli); } else if( furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_DELETE) == 0 || furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_DELETE_ALT) == 0) { diff --git a/applications/external/totp/cli/commands/details/details.c b/applications/external/totp/cli/commands/details/details.c index 7e714bf69..cc4c9eeff 100644 --- a/applications/external/totp/cli/commands/details/details.c +++ b/applications/external/totp/cli/commands/details/details.c @@ -7,33 +7,68 @@ #include "../../../ui/scene_director.h" #include "../../cli_helpers.h" #include "../../common_command_arguments.h" +#include "formatters/table/details_output_formatter_table.h" +#include "formatters/tsv/details_output_formatter_tsv.h" -#define TOTP_CLI_PRINTF_AUTOMATION_FEATURE(description, header_printed) \ - do { \ - TOTP_CLI_PRINTF( \ - "| %-20s | %-28.28s |\r\n", \ - header_printed ? "" : "Automation features", \ - description); \ - header_printed = true; \ - } while(false) +typedef void (*TOTP_CLI_DETAILS_HEADER_FORMATTER)(); +typedef void (*TOTP_CLI_DETAILS_FOOTER_FORMATTER)(); +typedef void (*TOTP_CLI_DETAILS_AUTOMATION_FEATURE_ITEM_FORMATTER)( + const char* key, + const char* feature, + bool* header_printed); +typedef void (*TOTP_CLI_DETAILS_CSTR_FORMATTER)(const char* key, const char* value); +typedef void (*TOTP_CLI_DETAILS_UINT8T_FORMATTER)(const char* key, uint8_t value); +typedef void (*TOTP_CLI_DETAILS_SIZET_FORMATTER)(const char* key, size_t value); -static void print_automation_features(const TokenInfo* token_info) { +typedef struct { + const TOTP_CLI_DETAILS_HEADER_FORMATTER header_formatter; + const TOTP_CLI_DETAILS_FOOTER_FORMATTER footer_formatter; + const TOTP_CLI_DETAILS_AUTOMATION_FEATURE_ITEM_FORMATTER automation_feature_item_formatter; + const TOTP_CLI_DETAILS_CSTR_FORMATTER cstr_formatter; + const TOTP_CLI_DETAILS_UINT8T_FORMATTER uint8t_formatter; + const TOTP_CLI_DETAILS_SIZET_FORMATTER sizet_formatter; +} TotpCliDetailsFormatter; + +static const TotpCliDetailsFormatter available_formatters[] = { + {.header_formatter = &details_output_formatter_print_header_table, + .footer_formatter = &details_output_formatter_print_footer_table, + .automation_feature_item_formatter = &details_output_formatter_print_automation_feature_table, + .cstr_formatter = &details_output_formatter_print_cstr_table, + .uint8t_formatter = &details_output_formatter_print_uint8t_table, + .sizet_formatter = &details_output_formatter_print_sizet_table}, + + {.header_formatter = &details_output_formatter_print_header_tsv, + .footer_formatter = &details_output_formatter_print_footer_tsv, + .automation_feature_item_formatter = &details_output_formatter_print_automation_feature_tsv, + .cstr_formatter = &details_output_formatter_print_cstr_tsv, + .uint8t_formatter = &details_output_formatter_print_uint8t_tsv, + .sizet_formatter = &details_output_formatter_print_sizet_tsv}, +}; + +static void print_automation_features( + const TokenInfo* token_info, + const TotpCliDetailsFormatter* formatter) { + bool header_printed = false; + const char* AUTOMATION_FEATURES_PRINT_KEY = "Automation features"; if(token_info->automation_features == TokenAutomationFeatureNone) { - TOTP_CLI_PRINTF("| %-20s | %-28.28s |\r\n", "Automation features", "None"); + (*formatter->automation_feature_item_formatter)( + AUTOMATION_FEATURES_PRINT_KEY, "None", &header_printed); return; } - bool header_printed = false; if(token_info->automation_features & TokenAutomationFeatureEnterAtTheEnd) { - TOTP_CLI_PRINTF_AUTOMATION_FEATURE("Type key at the end", header_printed); + (*formatter->automation_feature_item_formatter)( + AUTOMATION_FEATURES_PRINT_KEY, "Type key at the end", &header_printed); } if(token_info->automation_features & TokenAutomationFeatureTabAtTheEnd) { - TOTP_CLI_PRINTF_AUTOMATION_FEATURE("Type key at the end", header_printed); + (*formatter->automation_feature_item_formatter)( + AUTOMATION_FEATURES_PRINT_KEY, "Type key at the end", &header_printed); } if(token_info->automation_features & TokenAutomationFeatureTypeSlower) { - TOTP_CLI_PRINTF_AUTOMATION_FEATURE("Type slower", header_printed); + (*formatter->automation_feature_item_formatter)( + AUTOMATION_FEATURES_PRINT_KEY, "Type slower", &header_printed); } } @@ -64,6 +99,14 @@ void totp_cli_command_details_handle(PluginState* plugin_state, FuriString* args return; } + const TotpCliDetailsFormatter* formatter = &available_formatters[0]; + FuriString* arg = furi_string_alloc(); + if(args_read_string_and_trim(args, arg) && furi_string_cmpi_str(arg, "--tsv") == 0) { + formatter = &available_formatters[1]; + } + + furi_string_free(arg); + TOTP_CLI_LOCK_UI(plugin_state); size_t original_token_index = @@ -71,19 +114,14 @@ void totp_cli_command_details_handle(PluginState* plugin_state, FuriString* args if(totp_token_info_iterator_go_to(iterator_context, token_number - 1)) { const TokenInfo* token_info = totp_token_info_iterator_get_current_token(iterator_context); - TOTP_CLI_PRINTF("+----------------------+------------------------------+\r\n"); - TOTP_CLI_PRINTF("| %-20s | %-28s |\r\n", "Property", "Value"); - TOTP_CLI_PRINTF("+----------------------+------------------------------+\r\n"); - TOTP_CLI_PRINTF("| %-20s | %-28d |\r\n", "Index", token_number); - TOTP_CLI_PRINTF( - "| %-20s | %-28.28s |\r\n", "Name", furi_string_get_cstr(token_info->name)); - TOTP_CLI_PRINTF( - "| %-20s | %-28s |\r\n", "Hashing algorithm", token_info_get_algo_as_cstr(token_info)); - TOTP_CLI_PRINTF("| %-20s | %-28" PRIu8 " |\r\n", "Number of digits", token_info->digits); - TOTP_CLI_PRINTF( - "| %-20s | %" PRIu8 " sec.%-21s |\r\n", "Token lifetime", token_info->duration, " "); - print_automation_features(token_info); - TOTP_CLI_PRINTF("+----------------------+------------------------------+\r\n"); + (*formatter->header_formatter)(); + (*formatter->sizet_formatter)("Index", token_number); + (*formatter->cstr_formatter)("Name", furi_string_get_cstr(token_info->name)); + (*formatter->cstr_formatter)("Hashing algorithm", token_info_get_algo_as_cstr(token_info)); + (*formatter->uint8t_formatter)("Number of digits", token_info->digits); + (*formatter->uint8t_formatter)("Token lifetime", token_info->duration); + print_automation_features(token_info, formatter); + (*formatter->footer_formatter)(); } else { totp_cli_print_error_loading_token_info(); } diff --git a/applications/external/totp/cli/commands/details/formatters/table/details_output_formatter_table.c b/applications/external/totp/cli/commands/details/formatters/table/details_output_formatter_table.c new file mode 100644 index 000000000..44290db69 --- /dev/null +++ b/applications/external/totp/cli/commands/details/formatters/table/details_output_formatter_table.c @@ -0,0 +1,32 @@ +#include "details_output_formatter_table.h" +#include "../../../../cli_helpers.h" + +void details_output_formatter_print_header_table() { + TOTP_CLI_PRINTF("+----------------------+------------------------------+\r\n"); + TOTP_CLI_PRINTF("| %-20s | %-28s |\r\n", "Property", "Value"); + TOTP_CLI_PRINTF("+----------------------+------------------------------+\r\n"); +} + +void details_output_formatter_print_footer_table() { + TOTP_CLI_PRINTF("+----------------------+------------------------------+\r\n"); +} + +void details_output_formatter_print_automation_feature_table( + const char* key, + const char* feature, + bool* header_printed) { + TOTP_CLI_PRINTF("| %-20s | %-28.28s |\r\n", *header_printed ? "" : key, feature); + *header_printed = true; +} + +void details_output_formatter_print_cstr_table(const char* key, const char* value) { + TOTP_CLI_PRINTF("| %-20s | %-28.28s |\r\n", key, value); +} + +void details_output_formatter_print_uint8t_table(const char* key, uint8_t value) { + TOTP_CLI_PRINTF("| %-20s | %-28" PRIu8 " |\r\n", key, value); +} + +void details_output_formatter_print_sizet_table(const char* key, size_t value) { + TOTP_CLI_PRINTF("| %-20s | %-28" PRIu16 " |\r\n", key, value); +} diff --git a/applications/external/totp/cli/commands/details/formatters/table/details_output_formatter_table.h b/applications/external/totp/cli/commands/details/formatters/table/details_output_formatter_table.h new file mode 100644 index 000000000..bdb6bf115 --- /dev/null +++ b/applications/external/totp/cli/commands/details/formatters/table/details_output_formatter_table.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include +#include + +void details_output_formatter_print_header_table(); +void details_output_formatter_print_footer_table(); +void details_output_formatter_print_automation_feature_table( + const char* key, + const char* feature, + bool* header_printed); +void details_output_formatter_print_cstr_table(const char* key, const char* value); +void details_output_formatter_print_uint8t_table(const char* key, uint8_t value); +void details_output_formatter_print_sizet_table(const char* key, size_t value); diff --git a/applications/external/totp/cli/commands/details/formatters/tsv/details_output_formatter_tsv.c b/applications/external/totp/cli/commands/details/formatters/tsv/details_output_formatter_tsv.c new file mode 100644 index 000000000..39e61342c --- /dev/null +++ b/applications/external/totp/cli/commands/details/formatters/tsv/details_output_formatter_tsv.c @@ -0,0 +1,29 @@ +#include "details_output_formatter_tsv.h" +#include "../../../../cli_helpers.h" + +void details_output_formatter_print_header_tsv() { + TOTP_CLI_PRINTF("%s\t%s\r\n", "Property", "Value"); +} + +void details_output_formatter_print_footer_tsv() { +} + +void details_output_formatter_print_automation_feature_tsv( + const char* key, + const char* feature, + bool* header_printed) { + TOTP_CLI_PRINTF("%s\t%s\r\n", *header_printed ? "" : key, feature); + *header_printed = true; +} + +void details_output_formatter_print_cstr_tsv(const char* key, const char* value) { + TOTP_CLI_PRINTF("%s\t%s\r\n", key, value); +} + +void details_output_formatter_print_uint8t_tsv(const char* key, uint8_t value) { + TOTP_CLI_PRINTF("%s\t%" PRIu8 "\r\n", key, value); +} + +void details_output_formatter_print_sizet_tsv(const char* key, size_t value) { + TOTP_CLI_PRINTF("%s\t%" PRIu16 "\r\n", key, value); +} diff --git a/applications/external/totp/cli/commands/details/formatters/tsv/details_output_formatter_tsv.h b/applications/external/totp/cli/commands/details/formatters/tsv/details_output_formatter_tsv.h new file mode 100644 index 000000000..15b20ffcb --- /dev/null +++ b/applications/external/totp/cli/commands/details/formatters/tsv/details_output_formatter_tsv.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include +#include + +void details_output_formatter_print_header_tsv(); +void details_output_formatter_print_footer_tsv(); +void details_output_formatter_print_automation_feature_tsv( + const char* key, + const char* feature, + bool* header_printed); +void details_output_formatter_print_cstr_tsv(const char* key, const char* value); +void details_output_formatter_print_uint8t_tsv(const char* key, uint8_t value); +void details_output_formatter_print_sizet_tsv(const char* key, size_t value); diff --git a/applications/external/totp/cli/commands/list/formatters/table/list_output_formatter_table.c b/applications/external/totp/cli/commands/list/formatters/table/list_output_formatter_table.c new file mode 100644 index 000000000..8774a6edc --- /dev/null +++ b/applications/external/totp/cli/commands/list/formatters/table/list_output_formatter_table.c @@ -0,0 +1,22 @@ +#include "list_output_formatter_table.h" +#include "../../../../cli_helpers.h" + +void list_output_formatter_print_header_table() { + TOTP_CLI_PRINTF("+-----+---------------------------+--------+----+-----+\r\n"); + TOTP_CLI_PRINTF("| %-3s | %-25s | %-6s | %-s | %-s |\r\n", "#", "Name", "Algo", "Ln", "Dur"); + TOTP_CLI_PRINTF("+-----+---------------------------+--------+----+-----+\r\n"); +} + +void list_output_formatter_print_body_item_table(size_t index, const TokenInfo* token_info) { + TOTP_CLI_PRINTF( + "| %-3" PRIu16 " | %-25.25s | %-6s | %-2" PRIu8 " | %-3" PRIu8 " |\r\n", + index + 1, + furi_string_get_cstr(token_info->name), + token_info_get_algo_as_cstr(token_info), + token_info->digits, + token_info->duration); +} + +void list_output_formatter_print_footer_table() { + TOTP_CLI_PRINTF("+-----+---------------------------+--------+----+-----+\r\n"); +} \ No newline at end of file diff --git a/applications/external/totp/cli/commands/list/formatters/table/list_output_formatter_table.h b/applications/external/totp/cli/commands/list/formatters/table/list_output_formatter_table.h new file mode 100644 index 000000000..e2ed9c4dc --- /dev/null +++ b/applications/external/totp/cli/commands/list/formatters/table/list_output_formatter_table.h @@ -0,0 +1,9 @@ +#pragma once + +#include "../../../../../types/token_info.h" + +void list_output_formatter_print_header_table(); + +void list_output_formatter_print_body_item_table(size_t index, const TokenInfo* token_info); + +void list_output_formatter_print_footer_table(); \ No newline at end of file diff --git a/applications/external/totp/cli/commands/list/formatters/tsv/list_output_formatter_tsv.c b/applications/external/totp/cli/commands/list/formatters/tsv/list_output_formatter_tsv.c new file mode 100644 index 000000000..2bd455397 --- /dev/null +++ b/applications/external/totp/cli/commands/list/formatters/tsv/list_output_formatter_tsv.c @@ -0,0 +1,19 @@ +#include "list_output_formatter_tsv.h" +#include "../../../../cli_helpers.h" + +void list_output_formatter_print_header_tsv() { + TOTP_CLI_PRINTF("%s\t%s\t%s\t%s\t%s\r\n", "#", "Name", "Algo", "Ln", "Dur"); +} + +void list_output_formatter_print_body_item_tsv(size_t index, const TokenInfo* token_info) { + TOTP_CLI_PRINTF( + "%" PRIu16 "\t%s\t%s\t%" PRIu8 "\t%" PRIu8 "\r\n", + index + 1, + furi_string_get_cstr(token_info->name), + token_info_get_algo_as_cstr(token_info), + token_info->digits, + token_info->duration); +} + +void list_output_formatter_print_footer_tsv() { +} \ No newline at end of file diff --git a/applications/external/totp/cli/commands/list/formatters/tsv/list_output_formatter_tsv.h b/applications/external/totp/cli/commands/list/formatters/tsv/list_output_formatter_tsv.h new file mode 100644 index 000000000..e01c95d2e --- /dev/null +++ b/applications/external/totp/cli/commands/list/formatters/tsv/list_output_formatter_tsv.h @@ -0,0 +1,9 @@ +#pragma once + +#include "../../../../../types/token_info.h" + +void list_output_formatter_print_header_tsv(); + +void list_output_formatter_print_body_item_tsv(size_t index, const TokenInfo* token_info); + +void list_output_formatter_print_footer_tsv(); \ No newline at end of file diff --git a/applications/external/totp/cli/commands/list/list.c b/applications/external/totp/cli/commands/list/list.c index d5c97c6b0..1c39f3203 100644 --- a/applications/external/totp/cli/commands/list/list.c +++ b/applications/external/totp/cli/commands/list/list.c @@ -1,10 +1,32 @@ #include "list.h" #include +#include #include "../../../types/token_info.h" #include "../../../services/config/constants.h" #include "../../../services/config/config.h" #include "../../../ui/scene_director.h" #include "../../cli_helpers.h" +#include "formatters/table/list_output_formatter_table.h" +#include "formatters/tsv/list_output_formatter_tsv.h" + +typedef void (*TOTP_CLI_LIST_HEADER_FORMATTER)(); +typedef void (*TOTP_CLI_LIST_FOOTER_FORMATTER)(); +typedef void (*TOTP_CLI_LIST_BODY_ITEM_FORMATTER)(size_t index, const TokenInfo* token_info); + +typedef struct { + const TOTP_CLI_LIST_HEADER_FORMATTER header_formatter; + const TOTP_CLI_LIST_FOOTER_FORMATTER footer_formatter; + const TOTP_CLI_LIST_BODY_ITEM_FORMATTER body_item_formatter; +} TotpCliListFormatter; + +static const TotpCliListFormatter available_formatters[] = { + {.header_formatter = &list_output_formatter_print_header_table, + .body_item_formatter = &list_output_formatter_print_body_item_table, + .footer_formatter = &list_output_formatter_print_footer_table}, + + {.header_formatter = &list_output_formatter_print_header_tsv, + .body_item_formatter = &list_output_formatter_print_body_item_tsv, + .footer_formatter = &list_output_formatter_print_footer_tsv}}; #ifdef TOTP_CLI_RICH_HELP_ENABLED void totp_cli_command_list_docopt_commands() { @@ -18,7 +40,7 @@ void totp_cli_command_list_docopt_usage() { } #endif -void totp_cli_command_list_handle(PluginState* plugin_state, Cli* cli) { +void totp_cli_command_list_handle(PluginState* plugin_state, FuriString* args, Cli* cli) { if(!totp_cli_ensure_authenticated(plugin_state, cli)) { return; } @@ -31,26 +53,26 @@ void totp_cli_command_list_handle(PluginState* plugin_state, Cli* cli) { return; } + const TotpCliListFormatter* formatter = &available_formatters[0]; + FuriString* arg = furi_string_alloc(); + if(args_read_string_and_trim(args, arg) && furi_string_cmpi_str(arg, "--tsv") == 0) { + formatter = &available_formatters[1]; + } + + furi_string_free(arg); + TOTP_CLI_LOCK_UI(plugin_state); size_t original_index = totp_token_info_iterator_get_current_token_index(iterator_context); - TOTP_CLI_PRINTF("+-----+---------------------------+--------+----+-----+\r\n"); - TOTP_CLI_PRINTF("| %-3s | %-25s | %-6s | %-s | %-s |\r\n", "#", "Name", "Algo", "Ln", "Dur"); - TOTP_CLI_PRINTF("+-----+---------------------------+--------+----+-----+\r\n"); + (*formatter->header_formatter)(); for(size_t i = 0; i < total_count; i++) { totp_token_info_iterator_go_to(iterator_context, i); const TokenInfo* token_info = totp_token_info_iterator_get_current_token(iterator_context); - TOTP_CLI_PRINTF( - "| %-3" PRIu16 " | %-25.25s | %-6s | %-2" PRIu8 " | %-3" PRIu8 " |\r\n", - i + 1, - furi_string_get_cstr(token_info->name), - token_info_get_algo_as_cstr(token_info), - token_info->digits, - token_info->duration); + (*formatter->body_item_formatter)(i, token_info); } - TOTP_CLI_PRINTF("+-----+---------------------------+--------+----+-----+\r\n"); + (*formatter->footer_formatter)(); totp_token_info_iterator_go_to(iterator_context, original_index); diff --git a/applications/external/totp/cli/commands/list/list.h b/applications/external/totp/cli/commands/list/list.h index 8237bfd2b..0527e8c5f 100644 --- a/applications/external/totp/cli/commands/list/list.h +++ b/applications/external/totp/cli/commands/list/list.h @@ -7,7 +7,7 @@ #define TOTP_CLI_COMMAND_LIST "list" #define TOTP_CLI_COMMAND_LIST_ALT "ls" -void totp_cli_command_list_handle(PluginState* plugin_state, Cli* cli); +void totp_cli_command_list_handle(PluginState* plugin_state, FuriString* args, Cli* cli); #ifdef TOTP_CLI_RICH_HELP_ENABLED void totp_cli_command_list_docopt_commands(); void totp_cli_command_list_docopt_usage(); diff --git a/applications/external/totp/services/config/config.c b/applications/external/totp/services/config/config.c index 9320f4507..bd2d877b0 100644 --- a/applications/external/totp/services/config/config.c +++ b/applications/external/totp/services/config/config.c @@ -129,6 +129,17 @@ static bool totp_open_config_file(Storage* storage, FlipperFormat** file) { return false; } } else { + if(storage_common_stat(storage, CONFIG_FILE_DIRECTORY_PATH, NULL) == FSE_NOT_EXIST) { + FURI_LOG_D(LOGGING_TAG, "Config file directory doesn't exist. Will create new"); + if(!storage_simply_mkdir(storage, CONFIG_FILE_DIRECTORY_PATH)) { + FURI_LOG_E( + LOGGING_TAG, + "Error creating config file directory %s", + CONFIG_FILE_DIRECTORY_PATH); + return false; + } + } + FURI_LOG_D(LOGGING_TAG, "Config file %s is not found. Will create new.", CONFIG_FILE_PATH); if(!flipper_format_file_open_new(fff_data_file, CONFIG_FILE_PATH)) { diff --git a/applications/external/totp/totp_app.c b/applications/external/totp/totp_app.c index db1466893..adfd4a9a5 100644 --- a/applications/external/totp/totp_app.c +++ b/applications/external/totp/totp_app.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "config/app/config.h" #include "services/config/config.h" #include "types/plugin_state.h" @@ -237,6 +238,9 @@ int32_t totp_app() { return 253; } + // Affecting dolphin level + dolphin_deed(DolphinDeedPluginStart); + FuriMutex* main_loop_mutex = furi_mutex_alloc(FuriMutexTypeNormal); struct TotpRenderCallbackContext render_context = { .plugin_state = plugin_state, .mutex = main_loop_mutex}; diff --git a/applications/external/totp/ui/scenes/app_settings/totp_app_settings.c b/applications/external/totp/ui/scenes/app_settings/totp_app_settings.c index 252829432..9369ad44d 100644 --- a/applications/external/totp/ui/scenes/app_settings/totp_app_settings.c +++ b/applications/external/totp/ui/scenes/app_settings/totp_app_settings.c @@ -1,6 +1,7 @@ #include "totp_app_settings.h" #include -#include +#include "totp_icons.h" +#include #include #include "../../canvas_extensions.h" #include "../../ui_controls.h" diff --git a/applications/external/totp/ui/scenes/authenticate/totp_scene_authenticate.c b/applications/external/totp/ui/scenes/authenticate/totp_scene_authenticate.c index 01a5e6cb7..6913b99e8 100644 --- a/applications/external/totp/ui/scenes/authenticate/totp_scene_authenticate.c +++ b/applications/external/totp/ui/scenes/authenticate/totp_scene_authenticate.c @@ -1,6 +1,6 @@ #include "totp_scene_authenticate.h" #include -#include +#include "totp_icons.h" #include #include "../../../types/common.h" #include "../../constants.h" diff --git a/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.c b/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.c index 2d309609f..230438e63 100644 --- a/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.c +++ b/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.c @@ -2,7 +2,7 @@ #include #include #include -#include +#include "totp_icons.h" #include #include #include @@ -246,7 +246,7 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_ SCREEN_HEIGHT_CENTER + 10, AlignCenter, AlignCenter, - "Press OK button to access menu"); + "Press OK button to open menu"); return; } diff --git a/applications/external/totp/ui/scenes/standby/standby.c b/applications/external/totp/ui/scenes/standby/standby.c index 8524cf2a8..14408ba55 100644 --- a/applications/external/totp/ui/scenes/standby/standby.c +++ b/applications/external/totp/ui/scenes/standby/standby.c @@ -1,5 +1,5 @@ #include "standby.h" -#include +#include "totp_icons.h" #include #include "../../constants.h" @@ -10,4 +10,4 @@ void totp_scene_standby_render(Canvas* const canvas) { canvas_draw_str_aligned(canvas, 5, 10, AlignLeft, AlignTop, "CLI command"); canvas_draw_str_aligned(canvas, 5, 24, AlignLeft, AlignTop, "is running now"); -} +} \ No newline at end of file diff --git a/applications/external/totp/ui/ui_controls.c b/applications/external/totp/ui/ui_controls.c index 438556813..2bd31f931 100644 --- a/applications/external/totp/ui/ui_controls.c +++ b/applications/external/totp/ui/ui_controls.c @@ -1,5 +1,5 @@ #include "ui_controls.h" -#include +#include "totp_icons.h" #include #include "constants.h" diff --git a/applications/external/totp/version.h b/applications/external/totp/version.h index 8b77b9cd3..0b8597b0c 100644 --- a/applications/external/totp/version.h +++ b/applications/external/totp/version.h @@ -2,4 +2,4 @@ #define TOTP_APP_VERSION_MAJOR (4) #define TOTP_APP_VERSION_MINOR (0) -#define TOTP_APP_VERSION_PATCH (1) \ No newline at end of file +#define TOTP_APP_VERSION_PATCH (3) \ No newline at end of file diff --git a/applications/external/totp/workers/bt_type_code/bt_type_code.c b/applications/external/totp/workers/bt_type_code/bt_type_code.c index 39f2c565e..eff707099 100644 --- a/applications/external/totp/workers/bt_type_code/bt_type_code.c +++ b/applications/external/totp/workers/bt_type_code/bt_type_code.c @@ -230,4 +230,4 @@ void totp_bt_type_code_worker_free(TotpBtTypeCodeWorkerContext* context) { bool totp_bt_type_code_worker_is_advertising(const TotpBtTypeCodeWorkerContext* context) { return context->is_advertising; -} +} \ No newline at end of file diff --git a/applications/external/tuning_fork/application.fam b/applications/external/tuning_fork/application.fam index 350eeb573..5e86a6ad1 100644 --- a/applications/external/tuning_fork/application.fam +++ b/applications/external/tuning_fork/application.fam @@ -10,7 +10,6 @@ App( fap_icon="tuning_fork_icon.png", fap_category="Media", stack_size=2 * 1024, - order=20, fap_author="@besya & (Fixes by @Willy-JL)", fap_weburl="https://github.com/besya/flipperzero-tuning-fork", fap_version="1.0", diff --git a/applications/external/uart_terminal/application.fam b/applications/external/uart_terminal/application.fam index 6d7e63d6d..1416c6d57 100644 --- a/applications/external/uart_terminal/application.fam +++ b/applications/external/uart_terminal/application.fam @@ -1,14 +1,14 @@ App( appid="uart_terminal", - name="[UART] Terminal", + name="[UART] UART Terminal", apptype=FlipperAppType.EXTERNAL, entry_point="uart_terminal_app", requires=["gui"], stack_size=1 * 1024, - order=90, fap_icon="uart_terminal.png", fap_category="GPIO", + fap_icon_assets="assets", fap_author="@cool4uma & (some fixes by @xMasterX)", - fap_version="1.0", - fap_description="App to control various devices via UART interface.", + fap_version="1.1", + fap_description="Control various devices via the Flipper Zero UART interface.", ) diff --git a/applications/external/unitemp/application.fam b/applications/external/unitemp/application.fam index 260069f3e..b3f9dec35 100644 --- a/applications/external/unitemp/application.fam +++ b/applications/external/unitemp/application.fam @@ -7,7 +7,6 @@ App( "gui", ], stack_size=2 * 1024, - order=100, fap_description="Universal temperature sensors reader", fap_version="1.4", fap_author="@quen0n & (fixes by @xMasterX)", diff --git a/applications/external/unitemp/views/General_view.c b/applications/external/unitemp/views/General_view.c index 0a8e8ad17..d0d269126 100644 --- a/applications/external/unitemp/views/General_view.c +++ b/applications/external/unitemp/views/General_view.c @@ -17,10 +17,11 @@ */ #include "UnitempViews.h" #include "unitemp_icons.h" +#include -extern const Icon I_ButtonRight_4x7; -extern const Icon I_ButtonLeft_4x7; -extern const Icon I_Ok_btn_9x9; +// extern const Icon I_ButtonRight_4x7; +// extern const Icon I_ButtonLeft_4x7; +// extern const Icon I_Ok_btn_9x9; static View* view; diff --git a/applications/external/unitemp/views/Widgets_view.c b/applications/external/unitemp/views/Widgets_view.c index 97505d925..3055930cf 100644 --- a/applications/external/unitemp/views/Widgets_view.c +++ b/applications/external/unitemp/views/Widgets_view.c @@ -17,8 +17,9 @@ */ #include "UnitempViews.h" #include "unitemp_icons.h" +#include -extern const Icon I_DolphinCommon_56x48; +// extern const Icon I_DolphinCommon_56x48; void unitemp_widgets_alloc(void) { app->widget = widget_alloc(); @@ -202,4 +203,4 @@ void unitemp_widget_about_switch(void) { view_set_previous_callback(widget_get_view(app->widget), _help_exit_callback); view_dispatcher_switch_to_view(app->view_dispatcher, UnitempViewWidget); -} \ No newline at end of file +} diff --git a/applications/external/videopoker/application.fam b/applications/external/videopoker/application.fam index 129881648..4997132f2 100644 --- a/applications/external/videopoker/application.fam +++ b/applications/external/videopoker/application.fam @@ -6,7 +6,6 @@ App( cdefines=["APP_VIDEOPOKER_GAME"], requires=["gui"], stack_size=2 * 1024, - order=270, fap_icon="pokerIcon.png", fap_category="Games", fap_author="@PixlEmly", diff --git a/applications/external/wav_player/application.fam b/applications/external/wav_player/application.fam index cc462d0ef..112add8ee 100644 --- a/applications/external/wav_player/application.fam +++ b/applications/external/wav_player/application.fam @@ -4,9 +4,9 @@ App( apptype=FlipperAppType.EXTERNAL, entry_point="wav_player_app", stack_size=4 * 1024, - order=46, 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_parser.c b/applications/external/wav_player/wav_parser.c index 8c1f22b19..1f534bacb 100644 --- a/applications/external/wav_player/wav_parser.c +++ b/applications/external/wav_player/wav_parser.c @@ -11,7 +11,7 @@ const char* format_text(FormatTag tag) { default: return "Unknown"; } -} +}; struct WavParser { WavHeaderChunk header; diff --git a/applications/external/wav_player/wav_parser.h b/applications/external/wav_player/wav_parser.h index 8d4139865..b442406f9 100644 --- a/applications/external/wav_player/wav_parser.h +++ b/applications/external/wav_player/wav_parser.h @@ -86,4 +86,4 @@ size_t wav_parser_get_data_len(WavParser* parser); #ifdef __cplusplus } -#endif +#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 index 14fd8a1e1..79462caf9 100644 --- a/applications/external/wav_player/wav_player.c +++ b/applications/external/wav_player/wav_player.c @@ -12,6 +12,7 @@ #include "wav_player_view.h" #include +#include "wav_player_icons.h" #include #define TAG "WavPlayer" diff --git a/applications/external/wav_player/wav_player_hal.c b/applications/external/wav_player/wav_player_hal.c index c7ea039e8..cf2688523 100644 --- a/applications/external/wav_player/wav_player_hal.c +++ b/applications/external/wav_player/wav_player_hal.c @@ -108,4 +108,4 @@ void wav_player_dma_start() { 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_view.c b/applications/external/wav_player/wav_player_view.c index 0cb04d23f..285b3dd33 100644 --- a/applications/external/wav_player/wav_player_view.c +++ b/applications/external/wav_player/wav_player_view.c @@ -199,4 +199,4 @@ void wav_player_view_set_ctrl_callback(WavPlayerView* wav_view, WavPlayerCtrlCal 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 index 02ed4479c..b7b0ef908 100644 --- a/applications/external/wav_player/wav_player_view.h +++ b/applications/external/wav_player/wav_player_view.h @@ -75,4 +75,4 @@ void wav_player_view_set_context(WavPlayerView* wav_view, void* context); #ifdef __cplusplus } -#endif +#endif \ No newline at end of file diff --git a/applications/external/weather_station/application.fam b/applications/external/weather_station/application.fam index 8dcaa1259..0221130a3 100644 --- a/applications/external/weather_station/application.fam +++ b/applications/external/weather_station/application.fam @@ -6,7 +6,8 @@ App( entry_point="weather_station_app", requires=["gui"], stack_size=4 * 1024, - order=50, + fap_description="Receive weather data from a wide range of supported Sub-1GHz remote sensor", + fap_version="1.1", fap_icon="weather_station_10px.png", fap_category="Sub-GHz", fap_icon_assets="images", diff --git a/applications/external/weather_station/helpers/weather_station_types.h b/applications/external/weather_station/helpers/weather_station_types.h index 111465978..e6c696bf8 100644 --- a/applications/external/weather_station/helpers/weather_station_types.h +++ b/applications/external/weather_station/helpers/weather_station_types.h @@ -3,7 +3,7 @@ #include #include -#define WS_VERSION_APP "0.8" +#define WS_VERSION_APP "1.1" #define WS_DEVELOPED "SkorP" #define WS_GITHUB "https://github.com/flipperdevices/flipperzero-firmware" diff --git a/applications/external/weather_station/protocols/auriol_ahfl.c b/applications/external/weather_station/protocols/auriol_ahfl.c new file mode 100644 index 000000000..80b89e380 --- /dev/null +++ b/applications/external/weather_station/protocols/auriol_ahfl.c @@ -0,0 +1,254 @@ +#include "auriol_ahfl.h" + +#define TAG "WSProtocolAuriol_AHFL" + +/* + * +Auriol AHFL 433B2 IPX4 sensor. + +Data layout: + IIIIIIII-B-X-CC-TTTTTTTTTTTT-HHHHHHH0-FFFF-SSSSSS +Exmpl.: 10111100-1-0-00-000011101000-01101100-0100-001011 + +- I: id, 8 bit +- B: where B is the battery status: 1=OK, 0=LOW, 1 bit +- X: tx-button, 1 bit (might not work) +- C: CC is the channel: 00=CH1, 01=CH2, 11=CH3, 2bit +- T: temperature, 12 bit: 2's complement, scaled by 10 +- H: humidity, 7 bits data, 1 bit 0 +- F: always 0x4 (0100) +- S: nibble sum, 6 bits + + * The sensor sends 42 bits 5 times, + * the packets are ppm modulated (distance coding) with a pulse of ~500 us + * followed by a short gap of ~1000 us for a 0 bit or a long ~2000 us gap for a + * 1 bit, the sync gap is ~4000 us. + * + */ + +#define AURIOL_AHFL_CONST_DATA 0b0100 + +static const SubGhzBlockConst ws_protocol_auriol_ahfl_const = { + .te_short = 500, + .te_long = 2000, + .te_delta = 150, + .min_count_bit_for_found = 42, +}; + +struct WSProtocolDecoderAuriol_AHFL { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + WSBlockGeneric generic; +}; + +struct WSProtocolEncoderAuriol_AHFL { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolEncoder encoder; + WSBlockGeneric generic; +}; + +typedef enum { + auriol_AHFLDecoderStepReset = 0, + auriol_AHFLDecoderStepSaveDuration, + auriol_AHFLDecoderStepCheckDuration, +} auriol_AHFLDecoderStep; + +const SubGhzProtocolDecoder ws_protocol_auriol_ahfl_decoder = { + .alloc = ws_protocol_decoder_auriol_ahfl_alloc, + .free = ws_protocol_decoder_auriol_ahfl_free, + + .feed = ws_protocol_decoder_auriol_ahfl_feed, + .reset = ws_protocol_decoder_auriol_ahfl_reset, + + .get_hash_data = ws_protocol_decoder_auriol_ahfl_get_hash_data, + .serialize = ws_protocol_decoder_auriol_ahfl_serialize, + .deserialize = ws_protocol_decoder_auriol_ahfl_deserialize, + .get_string = ws_protocol_decoder_auriol_ahfl_get_string, +}; + +const SubGhzProtocolEncoder ws_protocol_auriol_ahfl_encoder = { + .alloc = NULL, + .free = NULL, + + .deserialize = NULL, + .stop = NULL, + .yield = NULL, +}; + +const SubGhzProtocol ws_protocol_auriol_ahfl = { + .name = WS_PROTOCOL_AURIOL_AHFL_NAME, + .type = SubGhzProtocolWeatherStation, + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + + .decoder = &ws_protocol_auriol_ahfl_decoder, + .encoder = &ws_protocol_auriol_ahfl_encoder, +}; + +void* ws_protocol_decoder_auriol_ahfl_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + WSProtocolDecoderAuriol_AHFL* instance = malloc(sizeof(WSProtocolDecoderAuriol_AHFL)); + instance->base.protocol = &ws_protocol_auriol_ahfl; + instance->generic.protocol_name = instance->base.protocol->name; + return instance; +} + +void ws_protocol_decoder_auriol_ahfl_free(void* context) { + furi_assert(context); + WSProtocolDecoderAuriol_AHFL* instance = context; + free(instance); +} + +void ws_protocol_decoder_auriol_ahfl_reset(void* context) { + furi_assert(context); + WSProtocolDecoderAuriol_AHFL* instance = context; + instance->decoder.parser_step = auriol_AHFLDecoderStepReset; +} + +static bool ws_protocol_auriol_ahfl_check(WSProtocolDecoderAuriol_AHFL* instance) { + uint8_t type = (instance->decoder.decode_data >> 6) & 0x0F; + + if(type != AURIOL_AHFL_CONST_DATA) { + // Fail const data check + return false; + } + + uint64_t payload = instance->decoder.decode_data >> 6; + // Checksum is the last 6 bits of data + uint8_t checksum_received = instance->decoder.decode_data & 0x3F; + uint8_t checksum_calculated = 0; + for(uint8_t i = 0; i < 9; i++) { + checksum_calculated += (payload >> (i * 4)) & 0xF; + } + return checksum_received == checksum_calculated; +} + +/** + * Analysis of received data + * @param instance Pointer to a WSBlockGeneric* instance + */ +static void ws_protocol_auriol_ahfl_remote_controller(WSBlockGeneric* instance) { + instance->id = instance->data >> 34; + instance->battery_low = (instance->data >> 33) & 1; + instance->btn = (instance->data >> 32) & 1; + instance->channel = ((instance->data >> 30) & 0x3) + 1; + if(!((instance->data >> 29) & 1)) { + instance->temp = (float)((instance->data >> 18) & 0x07FF) / 10.0f; + } else { + instance->temp = (float)((~(instance->data >> 18) & 0x07FF) + 1) / -10.0f; + } + instance->humidity = (instance->data >> 11) & 0x7F; +} + +void ws_protocol_decoder_auriol_ahfl_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + WSProtocolDecoderAuriol_AHFL* instance = context; + + switch(instance->decoder.parser_step) { + case auriol_AHFLDecoderStepReset: + if((!level) && (DURATION_DIFF(duration, ws_protocol_auriol_ahfl_const.te_short * 18) < + ws_protocol_auriol_ahfl_const.te_delta)) { + //Found syncPrefix + instance->decoder.parser_step = auriol_AHFLDecoderStepSaveDuration; + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + } + break; + case auriol_AHFLDecoderStepSaveDuration: + if(level) { + instance->decoder.te_last = duration; + instance->decoder.parser_step = auriol_AHFLDecoderStepCheckDuration; + } else { + instance->decoder.parser_step = auriol_AHFLDecoderStepReset; + } + break; + case auriol_AHFLDecoderStepCheckDuration: + if(!level) { + if(DURATION_DIFF(instance->decoder.te_last, ws_protocol_auriol_ahfl_const.te_short) < + ws_protocol_auriol_ahfl_const.te_delta) { + if(DURATION_DIFF(duration, ws_protocol_auriol_ahfl_const.te_short * 18) < + ws_protocol_auriol_ahfl_const.te_delta * 8) { + //Found syncPostfix + instance->decoder.parser_step = auriol_AHFLDecoderStepReset; + if((instance->decoder.decode_count_bit == + ws_protocol_auriol_ahfl_const.min_count_bit_for_found) && + ws_protocol_auriol_ahfl_check(instance)) { + instance->generic.data = instance->decoder.decode_data; + instance->generic.data_count_bit = instance->decoder.decode_count_bit; + ws_protocol_auriol_ahfl_remote_controller(&instance->generic); + if(instance->base.callback) { + instance->base.callback(&instance->base, instance->base.context); + } + } else if(instance->decoder.decode_count_bit == 1) { + instance->decoder.parser_step = auriol_AHFLDecoderStepSaveDuration; + } + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + } else if( + DURATION_DIFF(duration, ws_protocol_auriol_ahfl_const.te_long) < + ws_protocol_auriol_ahfl_const.te_delta * 2) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + instance->decoder.parser_step = auriol_AHFLDecoderStepSaveDuration; + } else if( + DURATION_DIFF(duration, ws_protocol_auriol_ahfl_const.te_long * 2) < + ws_protocol_auriol_ahfl_const.te_delta * 4) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + instance->decoder.parser_step = auriol_AHFLDecoderStepSaveDuration; + } else { + instance->decoder.parser_step = auriol_AHFLDecoderStepReset; + } + } else { + instance->decoder.parser_step = auriol_AHFLDecoderStepReset; + } + } else { + instance->decoder.parser_step = auriol_AHFLDecoderStepReset; + } + break; + } +} + +uint8_t ws_protocol_decoder_auriol_ahfl_get_hash_data(void* context) { + furi_assert(context); + WSProtocolDecoderAuriol_AHFL* instance = context; + return subghz_protocol_blocks_get_hash_data( + &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); +} + +SubGhzProtocolStatus ws_protocol_decoder_auriol_ahfl_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset) { + furi_assert(context); + WSProtocolDecoderAuriol_AHFL* instance = context; + return ws_block_generic_serialize(&instance->generic, flipper_format, preset); +} + +SubGhzProtocolStatus + ws_protocol_decoder_auriol_ahfl_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + WSProtocolDecoderAuriol_AHFL* instance = context; + return ws_block_generic_deserialize_check_count_bit( + &instance->generic, flipper_format, ws_protocol_auriol_ahfl_const.min_count_bit_for_found); +} + +void ws_protocol_decoder_auriol_ahfl_get_string(void* context, FuriString* output) { + furi_assert(context); + WSProtocolDecoderAuriol_AHFL* instance = context; + furi_string_printf( + output, + "%s %dbit\r\n" + "Key:0x%lX%08lX\r\n" + "Sn:0x%lX Ch:%d Bat:%d\r\n" + "Temp:%3.1f C Hum:%d%%", + instance->generic.protocol_name, + instance->generic.data_count_bit, + (uint32_t)(instance->generic.data >> 32), + (uint32_t)(instance->generic.data), + instance->generic.id, + instance->generic.channel, + instance->generic.battery_low, + (double)instance->generic.temp, + instance->generic.humidity); +} \ No newline at end of file diff --git a/applications/external/weather_station/protocols/auriol_ahfl.h b/applications/external/weather_station/protocols/auriol_ahfl.h new file mode 100644 index 000000000..1e29bc8cc --- /dev/null +++ b/applications/external/weather_station/protocols/auriol_ahfl.h @@ -0,0 +1,80 @@ +#pragma once + +#include + +#include +#include +#include +#include "ws_generic.h" +#include + +#define WS_PROTOCOL_AURIOL_AHFL_NAME "Auriol AHFL" //Auriol AHFL 433B2 IPX4 + +typedef struct WSProtocolDecoderAuriol_AHFL WSProtocolDecoderAuriol_AHFL; +typedef struct WSProtocolEncoderAuriol_AHFL WSProtocolEncoderAuriol_AHFL; + +extern const SubGhzProtocolDecoder ws_protocol_auriol_ahfl_decoder; +extern const SubGhzProtocolEncoder ws_protocol_auriol_ahfl_encoder; +extern const SubGhzProtocol ws_protocol_auriol_ahfl; + +/** + * Allocate WSProtocolDecoderAuriol_AHFL. + * @param environment Pointer to a SubGhzEnvironment instance + * @return WSProtocolDecoderAuriol_AHFL* pointer to a WSProtocolDecoderAuriol_AHFL instance + */ +void* ws_protocol_decoder_auriol_ahfl_alloc(SubGhzEnvironment* environment); + +/** + * Free WSProtocolDecoderAuriol_AHFL. + * @param context Pointer to a WSProtocolDecoderAuriol_AHFL instance + */ +void ws_protocol_decoder_auriol_ahfl_free(void* context); + +/** + * Reset decoder WSProtocolDecoderAuriol_AHFL. + * @param context Pointer to a WSProtocolDecoderAuriol_AHFL instance + */ +void ws_protocol_decoder_auriol_ahfl_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a WSProtocolDecoderAuriol_AHFL instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void ws_protocol_decoder_auriol_ahfl_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a WSProtocolDecoderAuriol_AHFL instance + * @return hash Hash sum + */ +uint8_t ws_protocol_decoder_auriol_ahfl_get_hash_data(void* context); + +/** + * Serialize data WSProtocolDecoderAuriol_AHFL. + * @param context Pointer to a WSProtocolDecoderAuriol_AHFL instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param preset The modulation on which the signal was received, SubGhzRadioPreset + * @return status + */ +SubGhzProtocolStatus ws_protocol_decoder_auriol_ahfl_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset); + +/** + * Deserialize data WSProtocolDecoderAuriol_AHFL. + * @param context Pointer to a WSProtocolDecoderAuriol_AHFL instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return status + */ +SubGhzProtocolStatus + ws_protocol_decoder_auriol_ahfl_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a WSProtocolDecoderAuriol_AHFL instance + * @param output Resulting text + */ +void ws_protocol_decoder_auriol_ahfl_get_string(void* context, FuriString* output); diff --git a/applications/external/weather_station/protocols/protocol_items.c b/applications/external/weather_station/protocols/protocol_items.c index 93dc25488..e0ec86068 100644 --- a/applications/external/weather_station/protocols/protocol_items.c +++ b/applications/external/weather_station/protocols/protocol_items.c @@ -18,6 +18,7 @@ const SubGhzProtocol* weather_station_protocol_registry_items[] = { &ws_protocol_oregon_v1, &ws_protocol_tx_8300, &ws_protocol_wendox_w6726, + &ws_protocol_auriol_ahfl, }; const SubGhzProtocolRegistry weather_station_protocol_registry = { diff --git a/applications/external/weather_station/protocols/protocol_items.h b/applications/external/weather_station/protocols/protocol_items.h index 712eb07f2..7d9bda243 100644 --- a/applications/external/weather_station/protocols/protocol_items.h +++ b/applications/external/weather_station/protocols/protocol_items.h @@ -18,5 +18,6 @@ #include "oregon_v1.h" #include "tx_8300.h" #include "wendox_w6726.h" +#include "auriol_ahfl.h" extern const SubGhzProtocolRegistry weather_station_protocol_registry; diff --git a/applications/external/weather_station/scenes/weather_station_receiver.c b/applications/external/weather_station/scenes/weather_station_receiver.c index 64df21fc5..76d808e7e 100644 --- a/applications/external/weather_station/scenes/weather_station_receiver.c +++ b/applications/external/weather_station/scenes/weather_station_receiver.c @@ -138,7 +138,7 @@ void weather_station_scene_receiver_on_enter(void* context) { if(app->txrx->txrx_state == WSTxRxStateRx) { ws_rx_end(app); - } + }; if((app->txrx->txrx_state == WSTxRxStateIDLE) || (app->txrx->txrx_state == WSTxRxStateSleep)) { ws_begin( app, @@ -162,7 +162,7 @@ bool weather_station_scene_receiver_on_event(void* context, SceneManagerEvent ev if(app->txrx->txrx_state == WSTxRxStateRx) { ws_rx_end(app); ws_sleep(app); - } + }; app->txrx->hopper_state = WSHopperStateOFF; app->txrx->idx_menu_chosen = 0; subghz_receiver_set_rx_callback(app->txrx->receiver, NULL, app); diff --git a/applications/external/weather_station/views/weather_station_receiver.c b/applications/external/weather_station/views/weather_station_receiver.c index b3bcde591..488ef022f 100644 --- a/applications/external/weather_station/views/weather_station_receiver.c +++ b/applications/external/weather_station/views/weather_station_receiver.c @@ -1,6 +1,6 @@ #include "weather_station_receiver.h" #include "../weather_station_app_i.h" -#include +#include "weather_station_icons.h" #include #include diff --git a/applications/external/weather_station/weather_station_app_i.c b/applications/external/weather_station/weather_station_app_i.c index 9437f4cf4..e98c61ee5 100644 --- a/applications/external/weather_station/weather_station_app_i.c +++ b/applications/external/weather_station/weather_station_app_i.c @@ -145,7 +145,7 @@ void ws_hopper_update(WeatherStationApp* app) { if(app->txrx->txrx_state == WSTxRxStateRx) { ws_rx_end(app); - } + }; if(app->txrx->txrx_state == WSTxRxStateIDLE) { subghz_receiver_reset(app->txrx->receiver); app->txrx->preset->frequency = diff --git a/applications/external/wifi_deauther/application.fam b/applications/external/wifi_deauther/application.fam index 17c6978b9..770e99585 100644 --- a/applications/external/wifi_deauther/application.fam +++ b/applications/external/wifi_deauther/application.fam @@ -6,7 +6,6 @@ App( cdefines=["APP_WIFI_deauther"], requires=["gui"], stack_size=1 * 1024, - order=30, fap_icon="wifi_10px.png", fap_category="WiFi", fap_author="@Timmotools & @xMasterX", diff --git a/applications/external/wifi_marauder_companion/application.fam b/applications/external/wifi_marauder_companion/application.fam index 7b6e5740d..dab41464b 100644 --- a/applications/external/wifi_marauder_companion/application.fam +++ b/applications/external/wifi_marauder_companion/application.fam @@ -6,7 +6,6 @@ App( entry_point="wifi_marauder_app", requires=["gui"], stack_size=4 * 1024, - order=90, fap_icon="wifi_10px.png", fap_category="WiFi", fap_icon_assets="assets", diff --git a/applications/external/wifi_marauder_companion/docs/README.md b/applications/external/wifi_marauder_companion/docs/README.md deleted file mode 100644 index 40b7a5ad0..000000000 --- a/applications/external/wifi_marauder_companion/docs/README.md +++ /dev/null @@ -1,9 +0,0 @@ -## WiFi Marauder companion app for Flipper Zero - -Requires a connected dev board running Marauder FW. See install instructions from UberGuidoZ here: https://github.com/UberGuidoZ/Flipper/tree/main/Wifi_DevBoard#marauder-install-information - -## Support - -For app feedback, bugs, and feature requests, please create an issue here: https://github.com/0xchocolate/flipperzero-wifi-marauder/issues - -You can find me (0xchocolate) on discord as @cococode. diff --git a/applications/external/wifi_scanner/application.fam b/applications/external/wifi_scanner/application.fam index 14f06ff7a..cd007eb48 100644 --- a/applications/external/wifi_scanner/application.fam +++ b/applications/external/wifi_scanner/application.fam @@ -5,7 +5,6 @@ App( entry_point="wifi_scanner_app", requires=["gui"], stack_size=2 * 1024, - order=110, fap_icon="wifi_10px.png", fap_category="WiFi", fap_author="@SequoiaSan & @xMasterX", diff --git a/applications/external/wiiec/application.fam b/applications/external/wiiec/application.fam index e84bba620..3576caf46 100644 --- a/applications/external/wiiec/application.fam +++ b/applications/external/wiiec/application.fam @@ -16,7 +16,6 @@ App( # sdk_headers="", # --- Run-time info stack_size=2 * 1024, - order=20, # --- FAP details sources=["wii_*.c", "gfx/*.c"], # fap_weburl="https://github.com/csBlueChip/FlipperZero_plugin_WiiChuck/", diff --git a/applications/external/wire_tester/LICENSE b/applications/external/wire_tester/LICENSE new file mode 100644 index 000000000..c34fc9f11 --- /dev/null +++ b/applications/external/wire_tester/LICENSE @@ -0,0 +1,25 @@ +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/wire_tester.c b/applications/external/wire_tester/wire_tester.c index 8b1b565d1..3eef936a5 100644 --- a/applications/external/wire_tester/wire_tester.c +++ b/applications/external/wire_tester/wire_tester.c @@ -8,6 +8,7 @@ #include #include "wire_tester_icons.h" +#include //#define TAG "wire_tester" diff --git a/applications/external/yatzee/application.fam b/applications/external/yatzee/application.fam index f633d8102..46480eb21 100644 --- a/applications/external/yatzee/application.fam +++ b/applications/external/yatzee/application.fam @@ -5,7 +5,6 @@ App( entry_point="yatzee_main", requires=["gui"], stack_size=4 * 1024, - order=99, fap_icon="images/yatzee_icon_10px.png", fap_category="Games", fap_icon_assets="images", diff --git a/applications/external/zombiez/application.fam b/applications/external/zombiez/application.fam index ca6120899..898488826 100644 --- a/applications/external/zombiez/application.fam +++ b/applications/external/zombiez/application.fam @@ -5,7 +5,6 @@ App( entry_point="zombiez_game_app", requires=["gui"], stack_size=2 * 1024, - order=280, fap_icon="zombie_10px.png", fap_category="Games", fap_author="@DevMilanIan & @xMasterX, (original By @Dooskington)", diff --git a/applications/external/zombiez/zombiez.c b/applications/external/zombiez/zombiez.c index e8d974800..a9bf74f7a 100644 --- a/applications/external/zombiez/zombiez.c +++ b/applications/external/zombiez/zombiez.c @@ -2,6 +2,7 @@ #include #include #include +#include //ORIGINAL REPO: https://github.com/Dooskington/flipperzero-zombiez //AUTHORS: https://github.com/Dooskington | https://github.com/DevMilanIan @@ -231,6 +232,8 @@ static void tick(PluginState* const plugin_state) { free(z); plugin_state->zombies[i] = NULL; plugin_state->score++; + //if(plugin_state->score % 15 == 0) dolphin_deed(getRandomDeed()); + //} } else if(z->position.x <= WALL_X && z->position.x > 0) { // zombie got to the wall plugin_state->zombies_count -= 1; free(z); @@ -311,6 +314,9 @@ int32_t zombiez_game_app(void* p) { Gui* gui = furi_record_open(RECORD_GUI); gui_add_view_port(gui, view_port, GuiLayerFullscreen); + // Call dolphin deed on game start + dolphin_deed(DolphinDeedPluginGameStart); + PluginEvent event; bool isRunning = true; while(isRunning) { @@ -393,4 +399,4 @@ free_and_exit: furi_message_queue_free(event_queue); return return_code; -} +} \ No newline at end of file