|
@@ -0,0 +1,357 @@
|
|
|
+/**
|
|
|
+ * @file incbin.h
|
|
|
+ * @author Dale Weiler
|
|
|
+ * @brief Utility for including binary files
|
|
|
+ *
|
|
|
+ * Facilities for including binary files into the current translation unit and
|
|
|
+ * making use from them externally in other translation units.
|
|
|
+ */
|
|
|
+#ifndef INCBIN_HDR
|
|
|
+#define INCBIN_HDR
|
|
|
+#include <limits.h>
|
|
|
+#if defined(__AVX512BW__) || \
|
|
|
+ defined(__AVX512CD__) || \
|
|
|
+ defined(__AVX512DQ__) || \
|
|
|
+ defined(__AVX512ER__) || \
|
|
|
+ defined(__AVX512PF__) || \
|
|
|
+ defined(__AVX512VL__) || \
|
|
|
+ defined(__AVX512F__)
|
|
|
+# define INCBIN_ALIGNMENT_INDEX 6
|
|
|
+#elif defined(__AVX__) || \
|
|
|
+ defined(__AVX2__)
|
|
|
+# define INCBIN_ALIGNMENT_INDEX 5
|
|
|
+#elif defined(__SSE__) || \
|
|
|
+ defined(__SSE2__) || \
|
|
|
+ defined(__SSE3__) || \
|
|
|
+ defined(__SSSE3__) || \
|
|
|
+ defined(__SSE4_1__) || \
|
|
|
+ defined(__SSE4_2__) || \
|
|
|
+ defined(__neon__)
|
|
|
+# define INCBIN_ALIGNMENT_INDEX 4
|
|
|
+#elif ULONG_MAX != 0xffffffffu
|
|
|
+# define INCBIN_ALIGNMENT_INDEX 3
|
|
|
+# else
|
|
|
+# define INCBIN_ALIGNMENT_INDEX 2
|
|
|
+#endif
|
|
|
+
|
|
|
+/* Lookup table of (1 << n) where `n' is `INCBIN_ALIGNMENT_INDEX' */
|
|
|
+#define INCBIN_ALIGN_SHIFT_0 1
|
|
|
+#define INCBIN_ALIGN_SHIFT_1 2
|
|
|
+#define INCBIN_ALIGN_SHIFT_2 4
|
|
|
+#define INCBIN_ALIGN_SHIFT_3 8
|
|
|
+#define INCBIN_ALIGN_SHIFT_4 16
|
|
|
+#define INCBIN_ALIGN_SHIFT_5 32
|
|
|
+#define INCBIN_ALIGN_SHIFT_6 64
|
|
|
+
|
|
|
+/* Actual alignment value */
|
|
|
+#define INCBIN_ALIGNMENT \
|
|
|
+ INCBIN_CONCATENATE( \
|
|
|
+ INCBIN_CONCATENATE(INCBIN_ALIGN_SHIFT, _), \
|
|
|
+ INCBIN_ALIGNMENT_INDEX)
|
|
|
+
|
|
|
+/* Stringize */
|
|
|
+#define INCBIN_STR(X) \
|
|
|
+ #X
|
|
|
+#define INCBIN_STRINGIZE(X) \
|
|
|
+ INCBIN_STR(X)
|
|
|
+/* Concatenate */
|
|
|
+#define INCBIN_CAT(X, Y) \
|
|
|
+ X ## Y
|
|
|
+#define INCBIN_CONCATENATE(X, Y) \
|
|
|
+ INCBIN_CAT(X, Y)
|
|
|
+/* Deferred macro expansion */
|
|
|
+#define INCBIN_EVAL(X) \
|
|
|
+ X
|
|
|
+#define INCBIN_INVOKE(N, ...) \
|
|
|
+ INCBIN_EVAL(N(__VA_ARGS__))
|
|
|
+
|
|
|
+/* Green Hills uses a different directive for including binary data */
|
|
|
+#if defined(__ghs__)
|
|
|
+# define INCBIN_MACRO "\tINCBIN"
|
|
|
+#else
|
|
|
+# define INCBIN_MACRO ".incbin"
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifndef _MSC_VER
|
|
|
+# define INCBIN_ALIGN \
|
|
|
+ __attribute__((aligned(INCBIN_ALIGNMENT)))
|
|
|
+#else
|
|
|
+# define INCBIN_ALIGN __declspec(align(INCBIN_ALIGNMENT))
|
|
|
+#endif
|
|
|
+
|
|
|
+#if defined(__arm__) || /* GNU C and RealView */ \
|
|
|
+ defined(__arm) || /* Diab */ \
|
|
|
+ defined(_ARM) /* ImageCraft */
|
|
|
+# define INCBIN_ARM
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef __GNUC__
|
|
|
+/* Utilize .balign where supported */
|
|
|
+# define INCBIN_ALIGN_HOST ".balign " INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"
|
|
|
+# define INCBIN_ALIGN_BYTE ".balign 1\n"
|
|
|
+#elif defined(INCBIN_ARM)
|
|
|
+/*
|
|
|
+ * On arm assemblers, the alignment value is calculated as (1 << n) where `n' is
|
|
|
+ * the shift count. This is the value passed to `.align'
|
|
|
+ */
|
|
|
+# define INCBIN_ALIGN_HOST ".align" INCBIN_STRINGIZE(INCBIN_ALIGNMENT_INDEX) "\n"
|
|
|
+# define INCBIN_ALIGN_BYTE ".align 0\n"
|
|
|
+#else
|
|
|
+/* We assume other inline assembler's treat `.align' as `.balign' */
|
|
|
+# define INCBIN_ALIGN_HOST ".align" INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"
|
|
|
+# define INCBIN_ALIGN_BYTE ".align 1\n"
|
|
|
+#endif
|
|
|
+
|
|
|
+/* INCBIN_CONST is used by incbin.c generated files */
|
|
|
+#if defined(__cplusplus)
|
|
|
+# define INCBIN_EXTERNAL extern "C"
|
|
|
+# define INCBIN_CONST extern const
|
|
|
+#else
|
|
|
+# define INCBIN_EXTERNAL extern
|
|
|
+# define INCBIN_CONST const
|
|
|
+#endif
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Optionally override the linker section into which data is emitted.
|
|
|
+ *
|
|
|
+ * @warning If you use this facility, you'll have to deal with platform-specific linker output
|
|
|
+ * section naming on your own
|
|
|
+ *
|
|
|
+ * Overriding the default linker output section, e.g for esp8266/Arduino:
|
|
|
+ * @code
|
|
|
+ * #define INCBIN_OUTPUT_SECTION ".irom.text"
|
|
|
+ * #include "incbin.h"
|
|
|
+ * INCBIN(Foo, "foo.txt");
|
|
|
+ * // Data is emitted into program memory that never gets copied to RAM
|
|
|
+ * @endcode
|
|
|
+ */
|
|
|
+#if !defined(INCBIN_OUTPUT_SECTION)
|
|
|
+# if defined(__APPLE__)
|
|
|
+# define INCBIN_OUTPUT_SECTION ".const_data"
|
|
|
+# else
|
|
|
+# define INCBIN_OUTPUT_SECTION ".rodata"
|
|
|
+# endif
|
|
|
+#endif
|
|
|
+
|
|
|
+#if defined(__APPLE__)
|
|
|
+/* The directives are different for Apple branded compilers */
|
|
|
+# define INCBIN_SECTION INCBIN_OUTPUT_SECTION "\n"
|
|
|
+# define INCBIN_GLOBAL(NAME) ".globl " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
|
|
|
+# define INCBIN_INT ".long "
|
|
|
+# define INCBIN_MANGLE "_"
|
|
|
+# define INCBIN_BYTE ".byte "
|
|
|
+# define INCBIN_TYPE(...)
|
|
|
+#else
|
|
|
+# define INCBIN_SECTION ".section " INCBIN_OUTPUT_SECTION "\n"
|
|
|
+# define INCBIN_GLOBAL(NAME) ".global " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
|
|
|
+# define INCBIN_INT ".int "
|
|
|
+# if defined(__USER_LABEL_PREFIX__)
|
|
|
+# define INCBIN_MANGLE INCBIN_STRINGIZE(__USER_LABEL_PREFIX__)
|
|
|
+# else
|
|
|
+# define INCBIN_MANGLE ""
|
|
|
+# endif
|
|
|
+# if defined(INCBIN_ARM)
|
|
|
+/* On arm assemblers, `@' is used as a line comment token */
|
|
|
+# define INCBIN_TYPE(NAME) ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", %object\n"
|
|
|
+# elif defined(__MINGW32__) || defined(__MINGW64__)
|
|
|
+/* Mingw doesn't support this directive either */
|
|
|
+# define INCBIN_TYPE(NAME)
|
|
|
+# else
|
|
|
+/* It's safe to use `@' on other architectures */
|
|
|
+# define INCBIN_TYPE(NAME) ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", @object\n"
|
|
|
+# endif
|
|
|
+# define INCBIN_BYTE ".byte "
|
|
|
+#endif
|
|
|
+
|
|
|
+/* List of style types used for symbol names */
|
|
|
+#define INCBIN_STYLE_CAMEL 0
|
|
|
+#define INCBIN_STYLE_SNAKE 1
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Specify the prefix to use for symbol names.
|
|
|
+ *
|
|
|
+ * By default this is `g', producing symbols of the form:
|
|
|
+ * @code
|
|
|
+ * #include "incbin.h"
|
|
|
+ * INCBIN(Foo, "foo.txt");
|
|
|
+ *
|
|
|
+ * // Now you have the following symbols:
|
|
|
+ * // const unsigned char gFooData[];
|
|
|
+ * // const unsigned char *const gFooEnd;
|
|
|
+ * // const unsigned int gFooSize;
|
|
|
+ * @endcode
|
|
|
+ *
|
|
|
+ * If however you specify a prefix before including: e.g:
|
|
|
+ * @code
|
|
|
+ * #define INCBIN_PREFIX incbin
|
|
|
+ * #include "incbin.h"
|
|
|
+ * INCBIN(Foo, "foo.txt");
|
|
|
+ *
|
|
|
+ * // Now you have the following symbols instead:
|
|
|
+ * // const unsigned char incbinFooData[];
|
|
|
+ * // const unsigned char *const incbinFooEnd;
|
|
|
+ * // const unsigned int incbinFooSize;
|
|
|
+ * @endcode
|
|
|
+ */
|
|
|
+#if !defined(INCBIN_PREFIX)
|
|
|
+# define INCBIN_PREFIX g
|
|
|
+#endif
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Specify the style used for symbol names.
|
|
|
+ *
|
|
|
+ * Possible options are
|
|
|
+ * - INCBIN_STYLE_CAMEL "CamelCase"
|
|
|
+ * - INCBIN_STYLE_SNAKE "snake_case"
|
|
|
+ *
|
|
|
+ * Default option is *INCBIN_STYLE_CAMEL* producing symbols of the form:
|
|
|
+ * @code
|
|
|
+ * #include "incbin.h"
|
|
|
+ * INCBIN(Foo, "foo.txt");
|
|
|
+ *
|
|
|
+ * // Now you have the following symbols:
|
|
|
+ * // const unsigned char <prefix>FooData[];
|
|
|
+ * // const unsigned char *const <prefix>FooEnd;
|
|
|
+ * // const unsigned int <prefix>FooSize;
|
|
|
+ * @endcode
|
|
|
+ *
|
|
|
+ * If however you specify a style before including: e.g:
|
|
|
+ * @code
|
|
|
+ * #define INCBIN_STYLE INCBIN_STYLE_SNAKE
|
|
|
+ * #include "incbin.h"
|
|
|
+ * INCBIN(foo, "foo.txt");
|
|
|
+ *
|
|
|
+ * // Now you have the following symbols:
|
|
|
+ * // const unsigned char <prefix>foo_data[];
|
|
|
+ * // const unsigned char *const <prefix>foo_end;
|
|
|
+ * // const unsigned int <prefix>foo_size;
|
|
|
+ * @endcode
|
|
|
+ */
|
|
|
+#if !defined(INCBIN_STYLE)
|
|
|
+# define INCBIN_STYLE INCBIN_STYLE_CAMEL
|
|
|
+#endif
|
|
|
+
|
|
|
+/* Style lookup tables */
|
|
|
+#define INCBIN_STYLE_0_DATA Data
|
|
|
+#define INCBIN_STYLE_0_END End
|
|
|
+#define INCBIN_STYLE_0_SIZE Size
|
|
|
+#define INCBIN_STYLE_1_DATA _data
|
|
|
+#define INCBIN_STYLE_1_END _end
|
|
|
+#define INCBIN_STYLE_1_SIZE _size
|
|
|
+
|
|
|
+/* Style lookup: returning identifier */
|
|
|
+#define INCBIN_STYLE_IDENT(TYPE) \
|
|
|
+ INCBIN_CONCATENATE( \
|
|
|
+ INCBIN_STYLE_, \
|
|
|
+ INCBIN_CONCATENATE( \
|
|
|
+ INCBIN_EVAL(INCBIN_STYLE), \
|
|
|
+ INCBIN_CONCATENATE(_, TYPE)))
|
|
|
+
|
|
|
+/* Style lookup: returning string literal */
|
|
|
+#define INCBIN_STYLE_STRING(TYPE) \
|
|
|
+ INCBIN_STRINGIZE( \
|
|
|
+ INCBIN_STYLE_IDENT(TYPE)) \
|
|
|
+
|
|
|
+/* Generate the global labels by indirectly invoking the macro with our style
|
|
|
+ * type and concatenating the name against them. */
|
|
|
+#define INCBIN_GLOBAL_LABELS(NAME, TYPE) \
|
|
|
+ INCBIN_INVOKE( \
|
|
|
+ INCBIN_GLOBAL, \
|
|
|
+ INCBIN_CONCATENATE( \
|
|
|
+ NAME, \
|
|
|
+ INCBIN_INVOKE( \
|
|
|
+ INCBIN_STYLE_IDENT, \
|
|
|
+ TYPE))) \
|
|
|
+ INCBIN_INVOKE( \
|
|
|
+ INCBIN_TYPE, \
|
|
|
+ INCBIN_CONCATENATE( \
|
|
|
+ NAME, \
|
|
|
+ INCBIN_INVOKE( \
|
|
|
+ INCBIN_STYLE_IDENT, \
|
|
|
+ TYPE)))
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Externally reference binary data included in another translation unit.
|
|
|
+ *
|
|
|
+ * Produces three external symbols that reference the binary data included in
|
|
|
+ * another translation unit.
|
|
|
+ *
|
|
|
+ * The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
|
|
|
+ * "Data", as well as "End" and "Size" after. An example is provided below.
|
|
|
+ *
|
|
|
+ * @param NAME The name given for the binary data
|
|
|
+ *
|
|
|
+ * @code
|
|
|
+ * INCBIN_EXTERN(Foo);
|
|
|
+ *
|
|
|
+ * // Now you have the following symbols:
|
|
|
+ * // extern const unsigned char <prefix>FooData[];
|
|
|
+ * // extern const unsigned char *const <prefix>FooEnd;
|
|
|
+ * // extern const unsigned int <prefix>FooSize;
|
|
|
+ * @endcode
|
|
|
+ */
|
|
|
+#define INCBIN_EXTERN(NAME) \
|
|
|
+ INCBIN_EXTERNAL const INCBIN_ALIGN unsigned char \
|
|
|
+ INCBIN_CONCATENATE( \
|
|
|
+ INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
|
|
|
+ INCBIN_STYLE_IDENT(DATA))[]; \
|
|
|
+ INCBIN_EXTERNAL const INCBIN_ALIGN unsigned char *const \
|
|
|
+ INCBIN_CONCATENATE( \
|
|
|
+ INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
|
|
|
+ INCBIN_STYLE_IDENT(END)); \
|
|
|
+ INCBIN_EXTERNAL const unsigned int \
|
|
|
+ INCBIN_CONCATENATE( \
|
|
|
+ INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
|
|
|
+ INCBIN_STYLE_IDENT(SIZE))
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Include a binary file into the current translation unit.
|
|
|
+ *
|
|
|
+ * Includes a binary file into the current translation unit, producing three symbols
|
|
|
+ * for objects that encode the data and size respectively.
|
|
|
+ *
|
|
|
+ * The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
|
|
|
+ * "Data", as well as "End" and "Size" after. An example is provided below.
|
|
|
+ *
|
|
|
+ * @param NAME The name to associate with this binary data (as an identifier.)
|
|
|
+ * @param FILENAME The file to include (as a string literal.)
|
|
|
+ *
|
|
|
+ * @code
|
|
|
+ * INCBIN(Icon, "icon.png");
|
|
|
+ *
|
|
|
+ * // Now you have the following symbols:
|
|
|
+ * // const unsigned char <prefix>IconData[];
|
|
|
+ * // const unsigned char *const <prefix>IconEnd;
|
|
|
+ * // const unsigned int <prefix>IconSize;
|
|
|
+ * @endcode
|
|
|
+ *
|
|
|
+ * @warning This must be used in global scope
|
|
|
+ * @warning The identifiers may be different if INCBIN_STYLE is not default
|
|
|
+ *
|
|
|
+ * To externally reference the data included by this in another translation unit
|
|
|
+ * please @see INCBIN_EXTERN.
|
|
|
+ */
|
|
|
+#ifdef _MSC_VER
|
|
|
+#define INCBIN(NAME, FILENAME) \
|
|
|
+ INCBIN_EXTERN(NAME)
|
|
|
+#else
|
|
|
+#define INCBIN(NAME, FILENAME) \
|
|
|
+ __asm__(INCBIN_SECTION \
|
|
|
+ INCBIN_GLOBAL_LABELS(NAME, DATA) \
|
|
|
+ INCBIN_ALIGN_HOST \
|
|
|
+ INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) ":\n" \
|
|
|
+ INCBIN_MACRO " \"" FILENAME "\"\n" \
|
|
|
+ INCBIN_GLOBAL_LABELS(NAME, END) \
|
|
|
+ INCBIN_ALIGN_BYTE \
|
|
|
+ INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) ":\n" \
|
|
|
+ INCBIN_BYTE "1\n" \
|
|
|
+ INCBIN_GLOBAL_LABELS(NAME, SIZE) \
|
|
|
+ INCBIN_ALIGN_HOST \
|
|
|
+ INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(SIZE) ":\n" \
|
|
|
+ INCBIN_INT INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) " - " \
|
|
|
+ INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) "\n" \
|
|
|
+ ); \
|
|
|
+ INCBIN_EXTERN(NAME)
|
|
|
+
|
|
|
+#endif
|
|
|
+#endif
|