Написание двоичных литералов на C без stdio.h или math.h?

Итак, мне нужно написать двоичные литералы на C. Мой компилятор не понимает двоичные литералы. Я знаю, что есть расширение gcc для "0b", но это не вариант. Прежде чем сказать: "Зачем тебе это нужно? Хекс был изобретен по какой-то причине, нуб", выслушай меня...

Это в целях маскировки. Я портирую игру с Sega Genesis/Megadrive на Sega Saturn. Столкновение в указанной игре использует плитки 16x16. Каждый фрагмент 16x16 имеет двухбайтовое значение в формате SSTT YXII IIII IIII. SS - это надежность элемента мозаичного изображения в альтернативном слое столкновений, TT - это надежность элемента мозаичного изображения в слое нормального столкновения. 00 означает не сплошной, 01 означает верхний сплошной, 10 означает левый / правый / нижний сплошной, а 11 означает все сплошной. Y- флаг Y-flip, X- флаг X-flip, а II IIII IIII - это индекс плитки 16x16 для использования.

Вы можете (надеюсь) увидеть, почему я хотел бы представить их в двоичном виде. Я собираюсь написать 100-е из них, и гораздо проще думать о твердости в битах, а не о гексагоне. Гораздо проще взглянуть на 0b0110 и сказать: "Хорошо, мозаика альтернативных столкновений сверху вниз, а нормальная - снизу", чем смотреть 0x6 и делать то же самое. Если бы я хотел изменить вторую плитку так, чтобы она также была в верхней части, я бы просто изменил 0110 на 0101, чем понял, что мне нужно изменить 6 на 5. Надеюсь, вы понимаете, почему я хочу, чтобы она была записана в двоичном виде. Это один раз, когда проще.

В любом случае, я работаю над Sega Saturn. Это означает, что я застрял с каким-либо компилятором C (на самом деле я даже не уверен, какой это компилятор или какая версия C), поэтому я не могу использовать stdio.h, math.h или что-нибудь. Черт, мне пришлось написать макрос по модулю.

Я видел некоторые дурацкие (но работоспособные) решения, но все они, похоже, требуют stdio... Я бы предпочел, чтобы это был макрос или что-то такое, что компилятор достаточно умен, чтобы его пропустить. Каждый цикл и бит оперативной памяти имеют значение, когда вы работаете с 16 мегабитами оперативной памяти, но я бы предпочел написать 0101 0011 1111, а не 53f. Двоичный файл имеет очень простой для понимания формат, и я хотел бы написать его таким образом.

Заранее спасибо!

3 ответа

Для того, что вы хотите, я бы написал макрос:

#define TILE_VALUE(S, T, Y, X, I)  (((S) << 14) | ((T) << 12) | ((Y) << 11) | ((X) << 10) | (I))

Затем вы определяете инициализатор таблицы с помощью этого макроса

Вы можете использовать макросы как это:

#define BIN2(dig1, dig2) (dig1 << 1 | dig2)
#define BIN3(dig1, dig2, dig3) (dig1 << 2 | dig2 << 1 || dig3)

и так далее, сколько нужно для реализации. Тогда эквивалент 0b110 было бы BIN3(1, 1, 0),

Используйте макрос препроцессора для определения слов столкновения. Например,

#define BIT_PAIR_00  0
#define BIT_PAIR_01  1
#define BIT_PAIR_10  2
#define BIT_PAIR_11  3
#define BINARY2(nn) (BIT_PAIR_ ## nn)
#define COLLISION_PACK(ss, tt, yx, index) ((index & 0x3FF) | (BINARY2(ss) << 14) | (BINARY2(tt) << 12) | (BINARY2(yx) << 10) )

который позволяет вам использовать, например,

COLLISION_PACK(01, 00, 11, 142)   == 0x4c8e == 0b0100110010001110
COLLISION_PACK(00, 10, 00, 200)   == 0x20c8 == 0b0010000011001000
COLLISION_PACK(10, 01, 00, 0x1fe) == 0x91fe == 0b1001000111111110

Также можно использовать макросы для аргументов:

#define NONE     0u
#define TOP      1u
#define NOT_TOP  2u
#define ALL      3u

#define NO_FLIP  0u
#define FLIP_X   1u
#define FLIP_Y   2u
#define FLIP_XY  3u

#define COLLISION_PACK(ss, tt, flip, index) \
    ( ((index) & 0x3FFu)    | \
      (((flip) & 3u) << 10) | \
      (((tt) & 3u) << 12)   | \
      (((ss) & 3u) << 14)   )

который позволяет вам использовать, например,

COLLISION_PACK(SOLID_NONE,   SOLID_NONE,   FLIP_NONE,   1)
  == 0x0001 == 0b0000000000000001 == 00 00 00 0000000001
COLLISION_PACK(SOLID_NOTTOP, SOLID_TOP,    FLIP_X,      2)
  == 0x9402 == 0b1001010000000010 == 10 01 01 0000000010 
COLLISION_PACK(SOLID_ALL,    SOLID_NOTTOP, FLIP_XY, 0x1fe)
  == 0xedfe == 0b1110110111111110 == 11 10 11 0111111110
Другие вопросы по тегам