mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-10-19 03:45:06 +00:00
- The `/system` FAT volume is removed. Its files are embedded in the firmware as generated C arrays. - Default-size fonts are generated at build time and used from flash. - The LVGL task and the Launcher run on PSRAM-preferred stacks. A new kernel `file_ops` API takes the file work off those threads. - `MainDispatcher` is reimplemented as an on-demand task. - More long-lived state is allocated with the PSRAM-preferring helpers. - Other fixes and improvements
92 lines
3.3 KiB
Python
92 lines
3.3 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Embeds every file of an asset folder as a C byte array.
|
|
|
|
Usage: generate-assets.py <asset-folder> <output-folder>
|
|
|
|
Writes generated_assets.h and generated_assets.c. A file "fonts/AdwaitaSans.ttf" becomes the symbols
|
|
asset_fonts_AdwaitaSans_ttf (the bytes) and asset_fonts_AdwaitaSans_ttf_size (the byte count).
|
|
The size is also available as the constant asset_fonts_AdwaitaSans_ttf_SIZE for use in constant initializers.
|
|
Text files get an extra terminating 0 byte that is not part of the size, so they can be used as C strings.
|
|
Output files are only rewritten when their content changes, to avoid needless recompiles.
|
|
"""
|
|
import os
|
|
import re
|
|
import sys
|
|
|
|
TEXT_EXTENSIONS = {".pem", ".csv", ".html", ".json", ".codepoints", ".i18n", ".txt"}
|
|
|
|
|
|
def symbol_name(relative_path: str) -> str:
|
|
return "asset_" + re.sub(r"[^A-Za-z0-9]", "_", relative_path)
|
|
|
|
|
|
def write_if_changed(path: str, content: str):
|
|
if os.path.exists(path):
|
|
with open(path, "r", encoding="utf-8", newline="") as file:
|
|
if file.read() == content:
|
|
return
|
|
with open(path, "w", encoding="utf-8", newline="") as file:
|
|
file.write(content)
|
|
|
|
|
|
def main():
|
|
if len(sys.argv) != 3:
|
|
print(f"Usage: {sys.argv[0]} <asset-folder> <output-folder>")
|
|
sys.exit(1)
|
|
asset_folder = os.path.abspath(sys.argv[1])
|
|
output_folder = os.path.abspath(sys.argv[2])
|
|
os.makedirs(output_folder, exist_ok=True)
|
|
|
|
relative_paths = []
|
|
for directory, _, file_names in os.walk(asset_folder):
|
|
for file_name in file_names:
|
|
relative_paths.append(os.path.relpath(os.path.join(directory, file_name), asset_folder).replace(os.sep, "/"))
|
|
relative_paths.sort()
|
|
|
|
header = [
|
|
"// Generated by Buildscripts/generate-assets.py. Do not edit.",
|
|
"#pragma once",
|
|
"",
|
|
"#include <stddef.h>",
|
|
"#include <stdint.h>",
|
|
"",
|
|
"#ifdef __cplusplus",
|
|
'extern "C" {',
|
|
"#endif",
|
|
"",
|
|
]
|
|
source = [
|
|
"// Generated by Buildscripts/generate-assets.py. Do not edit.",
|
|
'#include "generated_assets.h"',
|
|
"",
|
|
]
|
|
for relative_path in relative_paths:
|
|
with open(os.path.join(asset_folder, relative_path), "rb") as file:
|
|
data = file.read()
|
|
symbol = symbol_name(relative_path)
|
|
size = len(data)
|
|
if os.path.splitext(relative_path)[1].lower() in TEXT_EXTENSIONS:
|
|
data += b"\0"
|
|
header.append(f"// {relative_path}")
|
|
header.append(f"extern const uint8_t {symbol}[];")
|
|
header.append(f"extern const size_t {symbol}_size;")
|
|
header.append(f"#define {symbol}_SIZE {size}")
|
|
source.append(f"// {relative_path}")
|
|
source.append(f"const uint8_t {symbol}[] = {{")
|
|
for offset in range(0, len(data), 24):
|
|
source.append(" " + ", ".join(f"0x{byte:02x}" for byte in data[offset:offset + 24]) + ",")
|
|
if len(data) == 0:
|
|
source.append(" 0")
|
|
source.append("};")
|
|
source.append(f"const size_t {symbol}_size = {size};")
|
|
source.append("")
|
|
header += ["", "#ifdef __cplusplus", "}", "#endif", ""]
|
|
|
|
write_if_changed(os.path.join(output_folder, "generated_assets.h"), "\n".join(header))
|
|
write_if_changed(os.path.join(output_folder, "generated_assets.c"), "\n".join(source))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|