/* * incbin.h — Portable binary embedding via assembler .incbin directive * * Usage: * INCBIN(myData, "path/to/file.bin"); * * This creates: * extern const unsigned char g_myData_data[]; // file contents * extern const unsigned char *g_myData_end; // one past end * extern const unsigned int g_myData_size; // byte count * * Compared to xxd -i hex arrays, this uses near-zero compile-time RAM * because the assembler streams the file directly into the object file * without building an AST for millions of array elements. * * Supports: GCC, Clang, MinGW (any target that uses GAS). * MSVC: not supported (would need a different strategy). * * Based on the public-domain incbin technique. * Adapted for DragonX Wallet by The Hush Developers, 2024-2026. */ #ifndef DRAGONX_INCBIN_H #define DRAGONX_INCBIN_H #ifdef __cplusplus extern "C" { #endif /* * Helper macros for token pasting and stringification. */ #define INCBIN_CAT(a, b) INCBIN_CAT_(a, b) #define INCBIN_CAT_(a, b) a ## b #define INCBIN_STR(x) INCBIN_STR_(x) #define INCBIN_STR_(x) #x /* * Section attribute: place embedded data in .rodata so it lives in the * read-only segment just like a normal const array would. */ #if defined(__APPLE__) # define INCBIN_SECTION ".const_data" # define INCBIN_MANGLE "_" #else # define INCBIN_SECTION ".rodata" # define INCBIN_MANGLE "" #endif /* * Alignment: 16 bytes is sufficient for SIMD loads if anyone ever * wants to process embedded data with SSE/NEON, and is a safe default. */ #define INCBIN_ALIGN 16 /* * INCBIN_EXTERN — declare the symbols (use in headers) */ #define INCBIN_EXTERN(NAME) \ extern const unsigned char INCBIN_CAT(g_, INCBIN_CAT(NAME, _data))[]; \ extern const unsigned char *INCBIN_CAT(g_, INCBIN_CAT(NAME, _end)); \ extern const unsigned int INCBIN_CAT(g_, INCBIN_CAT(NAME, _size)) /* * INCBIN — define the symbols + embed the file (use in ONE .cpp/.c file) * * NAME : C identifier prefix (no quotes) * FILE : path to the file to embed (string literal, relative to -I or absolute) * * The generated assembly: * .section .rodata * .balign 16 * .global g_NAME_data * g_NAME_data: * .incbin "FILE" * .global g_NAME_end * g_NAME_end: * .byte 0 // NUL sentinel for C string compatibility * .balign 4 * .global g_NAME_size * g_NAME_size: * .int g_NAME_end - g_NAME_data */ #define INCBIN(NAME, FILE) \ __asm__( \ ".section " INCBIN_SECTION "\n" \ ".balign " INCBIN_STR(INCBIN_ALIGN) "\n" \ ".global " INCBIN_MANGLE "g_" #NAME "_data\n" \ INCBIN_MANGLE "g_" #NAME "_data:\n" \ " .incbin \"" FILE "\"\n" \ ".global " INCBIN_MANGLE "g_" #NAME "_end\n" \ INCBIN_MANGLE "g_" #NAME "_end:\n" \ " .byte 0\n" \ ".balign 4\n" \ ".global " INCBIN_MANGLE "g_" #NAME "_size\n" \ INCBIN_MANGLE "g_" #NAME "_size:\n" \ " .int " INCBIN_MANGLE "g_" #NAME "_end - " \ INCBIN_MANGLE "g_" #NAME "_data\n" \ ".text\n" /* restore default section */ \ ); \ INCBIN_EXTERN(NAME) #ifdef __cplusplus } #endif #endif /* DRAGONX_INCBIN_H */