Small bump in the road

- Update assets and references for new project
- Revert DFU image and CLI motd
- Remove NSFW text and flag
- Remove credits animation (will be replaced with a setting menu soon)
- New EvilPortal example HTML and better error message
- Initial standalone naming for asset packs and mainmenu apps
- File migration fixes/improvements
- Remove hotfix workflow
This commit is contained in:
Willy-JL
2024-02-28 01:22:45 +00:00
parent fed49ad256
commit b7220237de
167 changed files with 1795 additions and 2096 deletions

20
lib/momentum/SConscript Normal file
View File

@@ -0,0 +1,20 @@
Import("env")
env.Append(
SDK_HEADERS=[
File("../../icons/assets_icons.h"),
File("momentum.h"),
],
LINT_SOURCES=[
Dir("."),
],
)
libenv = env.Clone(FW_LIB_NAME="momentum")
libenv.ApplyLibFlags()
sources = libenv.GlobRecursive("*.c")
lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources)
libenv.Install("${LIB_DIST_DIR}", lib)
Return("lib")

195
lib/momentum/assets.c Normal file
View File

@@ -0,0 +1,195 @@
#include "momentum.h"
#include <furi_hal.h>
#include <gui/icon_i.h>
#include <assets_icons.h>
#include <storage/storage.h>
#include <core/dangerous_defines.h>
#define TAG "AssetPacks"
#define ICONS_FMT ASSET_PACKS_PATH "/%s/Icons/%s"
#define FONTS_FMT ASSET_PACKS_PATH "/%s/Fonts/%s.u8f"
// See lib/u8g2/u8g2_font.c
#define U8G2_FONT_DATA_STRUCT_SIZE 23
AssetPacks asset_packs = {
.fonts = {NULL},
.font_params = {NULL},
};
static void
load_icon_animated(const Icon* replace, const char* name, FuriString* path, File* file) {
const char* pack = momentum_settings.asset_pack;
furi_string_printf(path, ICONS_FMT "/meta", pack, name);
if(storage_file_open(file, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
int32_t icon_width, icon_height, frame_rate, frame_count;
bool ok =
(storage_file_read(file, &icon_width, 4) == 4 &&
storage_file_read(file, &icon_height, 4) == 4 &&
storage_file_read(file, &frame_rate, 4) == 4 &&
storage_file_read(file, &frame_count, 4) == 4);
storage_file_close(file);
if(ok) {
uint8_t** frames = malloc(sizeof(const uint8_t*) * frame_count);
int i = 0;
for(; i < frame_count; i++) {
furi_string_printf(path, ICONS_FMT "/frame_%02d.bm", pack, name, i);
if(storage_file_open(
file, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
uint64_t size = storage_file_size(file);
frames[i] = malloc(size);
ok = storage_file_read(file, frames[i], size) == size;
storage_file_close(file);
if(ok) continue;
} else {
storage_file_close(file);
i--;
}
break;
}
if(i == frame_count) {
Icon* original = malloc(sizeof(Icon));
memcpy(original, replace, sizeof(Icon));
FURI_CONST_ASSIGN_PTR(replace->original, original);
FURI_CONST_ASSIGN(replace->width, icon_width);
FURI_CONST_ASSIGN(replace->height, icon_height);
FURI_CONST_ASSIGN(replace->frame_rate, frame_rate);
FURI_CONST_ASSIGN(replace->frame_count, frame_count);
FURI_CONST_ASSIGN_PTR(replace->frames, frames);
} else {
for(; i >= 0; i--) {
free(frames[i]);
}
free(frames);
}
}
}
storage_file_close(file);
}
static void load_icon_static(const Icon* replace, const char* name, FuriString* path, File* file) {
furi_string_printf(path, ICONS_FMT ".bmx", momentum_settings.asset_pack, name);
if(storage_file_open(file, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
uint64_t size = storage_file_size(file) - 8;
uint8_t* frame = malloc(size);
int32_t icon_width, icon_height;
if(storage_file_read(file, &icon_width, 4) == 4 &&
storage_file_read(file, &icon_height, 4) == 4 &&
storage_file_read(file, frame, size) == size) {
Icon* original = malloc(sizeof(Icon));
memcpy(original, replace, sizeof(Icon));
FURI_CONST_ASSIGN_PTR(replace->original, original);
uint8_t** frames = malloc(sizeof(const uint8_t*));
frames[0] = frame;
FURI_CONST_ASSIGN(replace->frame_rate, 0);
FURI_CONST_ASSIGN(replace->frame_count, 1);
FURI_CONST_ASSIGN(replace->width, icon_width);
FURI_CONST_ASSIGN(replace->height, icon_height);
FURI_CONST_ASSIGN_PTR(replace->frames, frames);
} else {
free(frame);
}
}
storage_file_close(file);
}
static void free_icon(const Icon* icon) {
uint8_t** frames = (void*)icon->frames;
int32_t frame_count = icon->frame_count;
Icon* original = icon->original;
memcpy((void*)icon, original, sizeof(Icon));
free(original);
for(int32_t i = 0; i < frame_count; i++) {
free(frames[i]);
}
free(frames);
}
static void load_font(Font font, const char* name, FuriString* path, File* file) {
furi_string_printf(path, FONTS_FMT, momentum_settings.asset_pack, name);
if(storage_file_open(file, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
uint64_t size = storage_file_size(file);
uint8_t* swap = malloc(size);
if(size > U8G2_FONT_DATA_STRUCT_SIZE && storage_file_read(file, swap, size) == size) {
asset_packs.fonts[font] = swap;
CanvasFontParameters* params = malloc(sizeof(CanvasFontParameters));
// See lib/u8g2/u8g2_font.c
params->leading_default = swap[10]; // max_char_height
params->leading_min = params->leading_default - 2; // good enough
params->height = MAX((int8_t)swap[15], 0); // ascent_para
params->descender = MAX((int8_t)swap[16], 0); // descent_para
asset_packs.font_params[font] = params;
} else {
free(swap);
}
}
storage_file_close(file);
}
static void free_font(Font font) {
free(asset_packs.fonts[font]);
asset_packs.fonts[font] = NULL;
free(asset_packs.font_params[font]);
asset_packs.font_params[font] = NULL;
}
static const char* font_names[] = {
[FontPrimary] = "Primary",
[FontSecondary] = "Secondary",
[FontKeyboard] = "Keyboard",
[FontBigNumbers] = "BigNumbers",
[FontBatteryPercent] = "BatteryPercent",
};
void asset_packs_init() {
const char* pack = momentum_settings.asset_pack;
if(pack[0] == '\0') return;
Storage* storage = furi_record_open(RECORD_STORAGE);
FuriString* p = furi_string_alloc();
FileInfo info;
furi_string_printf(p, ASSET_PACKS_PATH "/%s", pack);
if(storage_common_stat(storage, furi_string_get_cstr(p), &info) == FSE_OK &&
info.flags & FSF_DIRECTORY) {
File* f = storage_file_alloc(storage);
for(size_t i = 0; i < ICON_PATHS_COUNT; i++) {
if(ICON_PATHS[i].icon->original == NULL) {
if(ICON_PATHS[i].icon->frame_count > 1) {
load_icon_animated(ICON_PATHS[i].icon, ICON_PATHS[i].path, p, f);
} else {
load_icon_static(ICON_PATHS[i].icon, ICON_PATHS[i].path, p, f);
}
}
}
for(Font font = 0; font < FontTotalNumber; font++) {
load_font(font, font_names[font], p, f);
}
storage_file_free(f);
}
furi_string_free(p);
furi_record_close(RECORD_STORAGE);
}
void asset_packs_free() {
for(size_t i = 0; i < ICON_PATHS_COUNT; i++) {
if(ICON_PATHS[i].icon->original != NULL) {
free_icon(ICON_PATHS[i].icon);
}
}
for(Font font = 0; font < FontTotalNumber; font++) {
if(asset_packs.fonts[font] != NULL) {
free_font(font);
}
}
}

105
lib/momentum/momentum.h Normal file
View File

@@ -0,0 +1,105 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <furi_hal_serial_types.h>
#include <gui/canvas.h>
#ifdef __cplusplus
extern "C" {
#endif
#define MOMENTUM_SETTINGS_PATH CFG_PATH("momentum_settings.txt")
#define ASSET_PACKS_PATH EXT_PATH("asset_packs")
#define MAINMENU_APPS_PATH CFG_PATH("mainmenu_apps.txt")
#define ASSET_PACKS_NAME_LEN 32
typedef enum {
BatteryIconOff,
BatteryIconBar,
BatteryIconPercent,
BatteryIconInvertedPercent,
BatteryIconRetro3,
BatteryIconRetro5,
BatteryIconBarPercent,
BatteryIconCount,
} BatteryIcon;
typedef enum {
MenuStyleList,
MenuStyleWii,
MenuStyleDsi,
MenuStylePs4,
MenuStyleVertical,
MenuStyleC64,
MenuStyleCompact,
MenuStyleTerminal,
MenuStyleCount,
} MenuStyle;
typedef enum {
SpiDefault, // cs on pa4
SpiExtra, // cs on pc3
SpiCount,
} SpiHandle;
_Static_assert(sizeof(MenuStyle) == sizeof(uint8_t), "enum too big, fix load/save");
_Static_assert(sizeof(BatteryIcon) == sizeof(uint8_t), "enum too big, fix load/save");
_Static_assert(sizeof(SpiHandle) == sizeof(uint8_t), "enum too big, fix load/save");
_Static_assert(sizeof(FuriHalSerialId) == sizeof(uint8_t), "enum too big, fix load/save");
typedef struct {
char asset_pack[ASSET_PACKS_NAME_LEN];
uint32_t anim_speed;
int32_t cycle_anims;
bool unlock_anims;
MenuStyle menu_style;
bool lock_on_boot;
bool bad_pins_format;
bool allow_locked_rpc_commands;
bool lockscreen_poweroff;
bool lockscreen_time;
bool lockscreen_seconds;
bool lockscreen_date;
bool lockscreen_statusbar;
bool lockscreen_prompt;
bool lockscreen_transparent;
BatteryIcon battery_icon;
bool statusbar_clock;
bool status_icons;
bool bar_borders;
bool bar_background;
bool sort_dirs_first;
bool show_hidden_files;
bool show_internal_tab;
uint32_t favorite_timeout;
bool bad_bt;
bool bad_bt_remember;
bool dark_mode;
bool rgb_backlight;
uint32_t butthurt_timer;
uint32_t charge_cap;
SpiHandle spi_cc1101_handle;
SpiHandle spi_nrf24_handle;
FuriHalSerialId uart_esp_channel;
FuriHalSerialId uart_nmea_channel;
FuriHalSerialId uart_general_channel;
bool file_naming_prefix_after;
} MomentumSettings;
typedef struct {
uint8_t* fonts[FontTotalNumber];
CanvasFontParameters* font_params[FontTotalNumber];
} AssetPacks;
void momentum_settings_load();
void momentum_settings_save();
extern MomentumSettings momentum_settings;
void asset_packs_init();
void asset_packs_free();
extern AssetPacks asset_packs;
#ifdef __cplusplus
}
#endif

27
lib/momentum/namespoof.c Normal file
View File

@@ -0,0 +1,27 @@
#include "namespoof.h"
#include <furi_hal.h>
#include <flipper_format/flipper_format.h>
#define TAG "NameSpoof"
void namespoof_init() {
FuriString* str = furi_string_alloc();
Storage* storage = furi_record_open(RECORD_STORAGE);
FlipperFormat* file = flipper_format_file_alloc(storage);
do {
uint32_t version;
if(!flipper_format_file_open_existing(file, NAMESPOOF_PATH)) break;
if(!flipper_format_read_header(file, str, &version)) break;
if(furi_string_cmp_str(str, NAMESPOOF_HEADER)) break;
if(version != NAMESPOOF_VERSION) break;
if(!flipper_format_read_string(file, "Name", str)) break;
version_set_custom_name(NULL, strdup(furi_string_get_cstr(str)));
furi_hal_version_set_name(NULL);
} while(false);
flipper_format_free(file);
furi_record_close(RECORD_STORAGE);
furi_string_free(str);
}

7
lib/momentum/namespoof.h Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
#define NAMESPOOF_HEADER "Flipper Name File"
#define NAMESPOOF_VERSION 1
#define NAMESPOOF_PATH EXT_PATH("dolphin/name.txt")
void namespoof_init();

197
lib/momentum/settings.c Normal file
View File

@@ -0,0 +1,197 @@
#include "momentum.h"
#include <furi_hal.h>
#include <rgb_backlight.h>
#include <flipper_format/flipper_format.h>
#define TAG "MomentumSettings"
MomentumSettings momentum_settings = {
.asset_pack = "", // Default
.anim_speed = 100, // 100%
.cycle_anims = 0, // Meta.txt
.unlock_anims = false, // OFF
.menu_style = MenuStyleDsi, // DSi
.lock_on_boot = false, // OFF
.bad_pins_format = false, // OFF
.allow_locked_rpc_commands = false, // OFF
.lockscreen_poweroff = true, // ON
.lockscreen_time = true, // ON
.lockscreen_seconds = false, // OFF
.lockscreen_date = true, // ON
.lockscreen_statusbar = true, // ON
.lockscreen_prompt = true, // ON
.lockscreen_transparent = false, // OFF
.battery_icon = BatteryIconBarPercent, // Bar %
.statusbar_clock = false, // OFF
.status_icons = true, // ON
.bar_borders = true, // ON
.bar_background = false, // OFF
.sort_dirs_first = true, // ON
.show_hidden_files = false, // OFF
.show_internal_tab = false, // OFF
.favorite_timeout = 0, // OFF
.bad_bt = false, // USB
.bad_bt_remember = false, // OFF
.dark_mode = false, // OFF
.rgb_backlight = false, // OFF
.butthurt_timer = 21600, // 6 H
.charge_cap = 100, // 100%
.spi_cc1101_handle = SpiDefault, // &furi_hal_spi_bus_handle_external
.spi_nrf24_handle = SpiDefault, // &furi_hal_spi_bus_handle_external
.uart_esp_channel = FuriHalSerialIdUsart, // pin 13,14
.uart_nmea_channel = FuriHalSerialIdUsart, // pin 13,14
.uart_general_channel = FuriHalSerialIdUsart, // pin 13,14
.file_naming_prefix_after = false, // Before
};
typedef enum {
momentum_settings_type_str,
momentum_settings_type_int,
momentum_settings_type_uint,
momentum_settings_type_enum,
momentum_settings_type_bool,
} momentum_settings_type;
static const struct {
momentum_settings_type type;
const char* key;
void* val;
union {
size_t str_len;
struct {
int32_t i_min;
int32_t i_max;
};
struct {
uint32_t u_min;
uint32_t u_max;
};
uint8_t e_cnt;
};
#define clamp(t, min, max) .t##_min = min, .t##_max = max
#define setting(t, n) .type = momentum_settings_type##t, .key = #n, .val = &momentum_settings.n
#define setting_str(n) setting(_str, n), .str_len = sizeof(momentum_settings.n)
#define setting_int(n, min, max) setting(_int, n), clamp(i, min, max)
#define setting_uint(n, min, max) setting(_uint, n), clamp(u, min, max)
#define setting_enum(n, cnt) setting(_enum, n), .e_cnt = cnt
#define setting_bool(n) setting(_bool, n)
} momentum_settings_entries[] = {
{setting_str(asset_pack)},
{setting_uint(anim_speed, 25, 300)},
{setting_int(cycle_anims, -1, 86400)},
{setting_bool(unlock_anims)},
{setting_enum(menu_style, MenuStyleCount)},
{setting_bool(bad_pins_format)},
{setting_bool(allow_locked_rpc_commands)},
{setting_bool(lock_on_boot)},
{setting_bool(lockscreen_poweroff)},
{setting_bool(lockscreen_time)},
{setting_bool(lockscreen_seconds)},
{setting_bool(lockscreen_date)},
{setting_bool(lockscreen_statusbar)},
{setting_bool(lockscreen_prompt)},
{setting_bool(lockscreen_transparent)},
{setting_enum(battery_icon, BatteryIconCount)},
{setting_bool(statusbar_clock)},
{setting_bool(status_icons)},
{setting_bool(bar_borders)},
{setting_bool(bar_background)},
{setting_bool(sort_dirs_first)},
{setting_bool(show_hidden_files)},
{setting_bool(show_internal_tab)},
{setting_uint(favorite_timeout, 0, 60)},
{setting_bool(bad_bt)},
{setting_bool(bad_bt_remember)},
{setting_bool(dark_mode)},
{setting_bool(rgb_backlight)},
{setting_uint(butthurt_timer, 0, 172800)},
{setting_uint(charge_cap, 5, 100)},
{setting_enum(spi_cc1101_handle, SpiCount)},
{setting_enum(spi_nrf24_handle, SpiCount)},
{setting_enum(uart_esp_channel, FuriHalSerialIdMax)},
{setting_enum(uart_nmea_channel, FuriHalSerialIdMax)},
{setting_enum(uart_general_channel, FuriHalSerialIdMax)},
{setting_bool(file_naming_prefix_after)},
};
void momentum_settings_load() {
Storage* storage = furi_record_open(RECORD_STORAGE);
FlipperFormat* file = flipper_format_file_alloc(storage);
if(flipper_format_file_open_existing(file, MOMENTUM_SETTINGS_PATH)) {
FuriString* val_str = furi_string_alloc();
int32_t val_int;
uint32_t val_uint;
bool val_bool;
bool ok;
for(size_t entry_i = 0; entry_i < COUNT_OF(momentum_settings_entries); entry_i++) {
#define entry momentum_settings_entries[entry_i]
switch(entry.type) {
case momentum_settings_type_str:
ok = flipper_format_read_string(file, entry.key, val_str);
if(ok) strlcpy((char*)entry.val, furi_string_get_cstr(val_str), entry.str_len);
break;
case momentum_settings_type_int:
ok = flipper_format_read_int32(file, entry.key, &val_int, 1);
if(ok) *(int32_t*)entry.val = CLAMP(val_int, entry.i_max, entry.i_min);
break;
case momentum_settings_type_uint:
ok = flipper_format_read_uint32(file, entry.key, &val_uint, 1);
if(ok) *(uint32_t*)entry.val = CLAMP(val_uint, entry.u_max, entry.u_min);
break;
case momentum_settings_type_enum:
ok = flipper_format_read_uint32(file, entry.key, &val_uint, 1);
if(ok) *(uint8_t*)entry.val = CLAMP(val_uint, entry.e_cnt - 1U, 0U);
break;
case momentum_settings_type_bool:
ok = flipper_format_read_bool(file, entry.key, &val_bool, 1);
if(ok) *(bool*)entry.val = val_bool;
break;
default:
continue;
}
if(!ok) flipper_format_rewind(file);
}
furi_string_free(val_str);
}
flipper_format_free(file);
furi_record_close(RECORD_STORAGE);
rgb_backlight_load_settings(momentum_settings.rgb_backlight);
}
void momentum_settings_save() {
Storage* storage = furi_record_open(RECORD_STORAGE);
FlipperFormat* file = flipper_format_file_alloc(storage);
if(flipper_format_file_open_always(file, MOMENTUM_SETTINGS_PATH)) {
uint32_t tmp_enum;
for(size_t entry_i = 0; entry_i < COUNT_OF(momentum_settings_entries); entry_i++) {
#define entry momentum_settings_entries[entry_i]
switch(entry.type) {
case momentum_settings_type_str:
flipper_format_write_string_cstr(file, entry.key, (char*)entry.val);
break;
case momentum_settings_type_int:
flipper_format_write_int32(file, entry.key, (int32_t*)entry.val, 1);
break;
case momentum_settings_type_uint:
flipper_format_write_uint32(file, entry.key, (uint32_t*)entry.val, 1);
break;
case momentum_settings_type_enum:
tmp_enum = *(uint8_t*)entry.val;
flipper_format_write_uint32(file, entry.key, &tmp_enum, 1);
break;
case momentum_settings_type_bool:
flipper_format_write_bool(file, entry.key, (bool*)entry.val, 1);
break;
default:
continue;
}
}
}
flipper_format_free(file);
furi_record_close(RECORD_STORAGE);
}