use core::ffi::c_char;
use flipperzero_sys as sys;
const MANIFEST_MAGIC: u32 = 0x52474448;
const HARDWARE_TARGET: u16 = 7;
const DEFAULT_STACK_SIZE: u16 = 2048;
#[macro_export]
macro_rules! manifest {
($($field:ident = $value:expr),*) => {
#[no_mangle]
#[link_section = ".fapmeta"]
static FAP_MANIFEST: $crate::manifest::ApplicationManifestV1 = $crate::manifest::ApplicationManifestV1 {
$( $field: $crate::manifest::set::$field($value), )*
.. $crate::manifest::ApplicationManifestV1::default()
};
};
}
#[macro_export]
macro_rules! _manifest_field {
(stack_size = $value:expr) => {
stack_size: $value
};
(app_version = $value:expr) => {
app_version: $value
};
(name = $value:expr) => {
name: $crate::manifest::padded($value.as_bytes())
}
}
pub mod set {
use super::padded;
pub const fn stack_size(n_bytes: u16) -> u16 {
n_bytes
}
pub const fn app_version(version: u32) -> u32 {
version
}
pub const fn name<const SIZE: usize>(name: &str) -> [u8; SIZE] {
padded(name.as_bytes())
}
}
#[repr(C, packed)]
pub struct ManifestBase {
pub manifest_magic: u32,
pub manifest_version: u32,
pub api_version_major: u16,
pub api_version_minor: u16,
pub hardware_target_id: u16,
}
#[repr(C, packed)]
pub struct ApplicationManifestV1 {
pub base: ManifestBase,
pub stack_size: u16,
pub app_version: u32,
pub name: [u8; 32],
pub has_icon: c_char,
pub icon: [u8; 32],
}
impl ApplicationManifestV1 {
pub const fn default() -> Self {
Self {
base: ManifestBase {
manifest_magic: MANIFEST_MAGIC,
manifest_version: 1,
api_version_major: (sys::API_VERSION >> 16) as u16,
api_version_minor: (sys::API_VERSION & 0x0000FFFF) as u16,
hardware_target_id: HARDWARE_TARGET,
},
stack_size: DEFAULT_STACK_SIZE,
app_version: 1,
name: padded(b"Application"),
has_icon: 0,
icon: [0; 32],
}
}
}
const fn padded<const SIZE: usize>(value: &[u8]) -> [u8; SIZE] {
let mut array: [u8; SIZE] = [0; SIZE];
let mut i = 0;
while i < array.len() - 1 && i < value.len() {
array[i] = value[i];
i += 1;
}
array[i] = 0;
array
}