mirror of
https://github.com/buserror/mii_emu.git
synced 2024-11-22 16:33:01 +00:00
380 lines
12 KiB
C
380 lines
12 KiB
C
|
/**
|
||
|
* @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>
|
||
|
|
||
|
// Michel addition:
|
||
|
// Allow the included file to have an extra zero, to include text files
|
||
|
// as plain zero terminated strings
|
||
|
#ifdef INCBIN_TRAILING_ZERO
|
||
|
#define INCBIN_TRAIL INCBIN_BYTE "0\n"
|
||
|
#else
|
||
|
#define INCBIN_TRAIL
|
||
|
#endif
|
||
|
|
||
|
#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__)
|
||
|
# if (__ghs_asm == 2)
|
||
|
# define INCBIN_MACRO ".file"
|
||
|
/* Or consider the ".myrawdata" entry in the ld file */
|
||
|
# else
|
||
|
# define INCBIN_MACRO "\tINCBIN"
|
||
|
# endif
|
||
|
#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_MANGLE 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"
|
||
|
# if defined(__ghs__)
|
||
|
# define INCBIN_INT ".word "
|
||
|
# else
|
||
|
# define INCBIN_INT ".int "
|
||
|
# endif
|
||
|
# 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_TRAIL \
|
||
|
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_ALIGN_HOST \
|
||
|
".text\n" \
|
||
|
); \
|
||
|
INCBIN_EXTERN(NAME)
|
||
|
|
||
|
#endif
|
||
|
#endif
|