...

воскресенье, 30 августа 2020 г.

Как я участвовал в IOCCC-'19 (и проиграл). Часть 2: «Симулятор NOR»

Это вторая часть цикла статей о том, как я участвовал в IOCCC'19

  1. Как я участвовал в IOCCC-'19 (и проиграл). Часть 1: «Крестики-нолики»
  2. Как я участвовал в IOCCC-'19 (и проиграл). Часть 2: «Симулятор NOR»

Я надеюсь, что данная статья поможет вам при разборе чужого кода или кода после декомпилятора или обфускатора.

Если вы еще не знаете, что такое IOCCC или вы хотите ознакомиться с более простым вариантом запутанного кода, то рекомендую обратиться к первой части.

Всем остальным я желаю приятного чтения.


Все исходники помещены на github, откуда их можно невозбранно скачать и попробовать скомпилировать.

Исходные данные


Так как исходный код в текстовом виде можно найти по ссылке, покажу как код выглядит графически:

Традиционно сложилось, что «дополнительные баллы» даются, если код отформатирован нестандартно или выглядит как какое-то изображение. Что ж, будем считать, это с этим здесь всё в порядке.

Но что же делает программа?

Она инициализирует графический стек X-сервера, сканирует предоставленный файл конфигурации, рисует электрическую схему согласно файлу и запускает симуляцию, поочередно меняя полярность на 4 ножках входа, используя при этом только NOR (Not-OR) элементы. Отрисовка происходит с шейдером старого LCD-экрана.

В комплекте с программой идут несколько конфигурационных файлов, а именно:

DIP8-4packnot.txt — примерный аналог CMOS 4041/Четырехканальный инвертор



(изображение сжато в 2 раза, чтобы уместиться в рамки приличия. На самом деле забавно, что программа, весом в 3.5 КБ генерирует ряд изображений, который в максимальном сжатии занимают 10.5+МБ)

DIP8-triplexor.txt — примерный аналог CMOS 4030 с объединенными входами и тремя каналами/Трехканальный XOR-gate с объединенными входами


DIP8-fulladder.txt — примерный аналог CMOS 4008, но на два бита/сумматор на 2 бита с выводом бита переноса


Разбор кода

Самой сложной задачей в этот раз было уместиться в ограничение по размеру присылаемой работы. Ограничен не только размер файла, но и количество условных «токенов» — символов операций, ключевых слов языка и пар скобок. Именно для того, чтобы «заэксплойтить» эту особенность парсера-проверяльщика размера в программе объявлено огромное количество define'ов, приводящих блоки кода к одному ключевому слову языка С.

Для начала, заглянем в Makefile, чтобы понять, как код собирается:
#!/usr/bin/env make
PROJECT=prog
CC= gcc
SRC=prog.c
CWARN=-Wall -Wextra -Wno-char-subscripts

CSTD= -std=c99
# Syscalls table
# DS - syscall nanosleep
# DO - syscall open
# DR - syscall read
# DC - syscall close

# X11 structures offsets
# dS - offset of screens in Display
# dR - offset of root in Screen
# dD - offset of root_depth in Screen
# dV - offset of root_visual in Screen
# dG - offset of default_gc in Screen

BITS := $(shell uname -p)

ifeq ($(BITS), x86_64)
ARCH= -m64
CDEFINE= -DDS=35 -DDO=2 -DDR=0 -DDC=3 -DdS=232 -DdR=16 -DdD=56 -DdV=64 -DdG=72
else
ARCH= -m32
CDEFINE= -DDS=162 -DDO=5 -DDR=3 -DDC=6 -DdS=140 -DdR=8 -DdD=36 -DdV=40 -DdG=44
endif

OPT= -g

CFLAGS= ${CWARN} ${CSTD} ${ARCH} ${CDEFINE} ${OPT}
LDFLAGS= -ldl

RM= rm

all: ${PROJECT}

${PROJECT}:
${CC} ${CFLAGS} ${SRC} -o $@ ${LDFLAGS}
clean:
${RM} -f ${PROJECT}

Как видим, эта работа, так же, как и предыдущая активно использует системные вызовы, чтобы избежать уродливых "#include", которые нарушают узор картинки. Запомним этот факт и подготовим строку для препроцессора и линтера:

После препроцессора
gcc -DDS=35 -DDO=2 -DDR=0 -DDC=3 -DdS=232 -DdR=16 -DdD=56 -DdV=64 -DdG=72 prog.c -ldl -E | indent -kr -brf > /tmp/fmt.c
:
int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };

extern void *dlsym(void *, char *);
int x_[616][1220];
extern long syscall(long, ...);
extern void *dlopen(char *, int);
char m[19][20], _n[] =
    "pu~D--2os" "<<<<<<<<" "<<<DSlyrXuolp}e" "<<<<<<<<"
    "D_ny}hyOuqlpyKurxsk<D_ny" "}hyUq}{y" "<<<<<<<<" "DLihUq}{y" "<<<<<<<<"
    "<<<DQ}lKurxsk" "<<<<<<<<" "<<DZpiot<";
long w, N[2] = { 0, 1 << 29 };
int rn = 2166136261, _[8][40][64] = { 0 };
long R[2];
void *M, *d, *T;

void b(int t, int x, int y, int c, int l) {
    if ((x >= 19 || y >= 19 || x < 0 || y < 0) || (m[y][x] == l)
        || (m[y][x] != c))
        return;
    m[y][x] = l;
    b(t, x - 1, y, c, l);
    b(t, x + 1, y, c, l);
    b(t, x, y - 1, c, l);
    b(t, x, y + 1, c, l);
}

void e(int t, int x, int y, int c, int l) {
    if ((x >= 64 || y >= 40 || x < 0 || y < 0) || (_[t][y][x] == l)
        || (_[t][y][x] != c))
        return;
    _[t][y][x] = l;
    e(t, x - 1, y, c, l);
    e(t, x + 1, y, c, l);
    e(t, x, y - 1, c, l);
    e(t, x, y + 1, c, l);
}

void k(int t, int x, int y, int c, int l) {
    while (c--) {
        _[t][y][x++] = l;
        _[t][y++][x++] = l;
    }
}

void r(int t, int x, int y, int c, int l) {
    while (c--) {
        _[t][y][x--] = l;
        _[t][y++][x--] = l;
    }
}

void u(int t, int x, int y, int c, int l) {
    while (c--)
        _[t][y++][x] = l;
}

char *z[8] = { 
    (char[]) {4}, 
    (char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
                     21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
                     63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
                     32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
                     21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
                     36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
                     3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
        (char[]) {5, 1}, 
        (char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
                                   0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
                                   21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
                                   4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
                                   5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
                                   63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
                                   21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
                                   0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
                                   3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
                                   38 - 0,
                                   4},
        (char[]) {4}, (char[]) {4},
        (char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
                  21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
                  21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
                  16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
                  2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
                  3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
                  3, 30, 38 - 3, 4}, 
    (char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
                                               0, 8 + 0 + 0, 21, 12 - 0, 1,
                                               31, 9 + 0, 12 - 0, 1,
                                               55 - 0 - 0, 21, 12 - 0, 0,
                                               32, 9 + 3, 12 - 3, 0,
                                               8 + 3 + 3, 21, 12 - 3, 1,
                                               31, 9 + 3, 12 - 3, 1,
                                               55 - 3 - 3, 21, 12 - 3, 6,
                                               14 + 0, 2, 31 + 0, 13, 4,
                                               1 - 0, 31 + 0, 16, 7, 3,
                                               30 + 3 * 0, 14, 6,
                                               12 + 0 * 4, 3, 32 - 0,
                                               11 + 0 * 8, 6, 14 + 1, 2,
                                               31 + 1, 13, 4, 1 - 1,
                                               31 + 1, 16, 7, 3,
                                               30 + 3 * 1, 14, 6,
                                               12 + 1 * 4, 3, 32 - 1,
                                               11 + 1 * 8,
                                               4}
};

void d_(int t, int p, int q) {
    for (int y = 0; y < 40; y++)
        for (int x = 0; x < 64; x++)
            if (_[t]
                [y][x])
                x_[y + q * 16 + p * 16][x + 580 + p * 32 - q *
                                        32] = _[t][y][x];
}

int main(int a, char *s[]) {
    int h = 127;
    while (h--) {
        _n[h] ^= 28;
        _n[h] -= (_n[h] == 32 ? 32 : 0);
    }
    T = dlopen(_n, 2);
    d = ((void *(*)()) dlsym(T, _n + (1 * 20))) (0);
    w = ((long (*)()) dlsym(T, _n + (2 * 20))) (d,
                                                (*(long *)
                                                 ((char
                                                   *) (*(long *) ((char *)
                                                                  d +
                                                                  232)) +
                                                  16))



                                                , 0, 0, 1220, 616, 1, 0,
                                                0);
    M = ((void *(*)()) dlsym(T, _n + (3 * 20))) (d,
                                                 (*(long *)
                                                  ((char
                                                    *) (*(long *) ((char *)
                                                                   d +
                                                                   232)) +
                                                   64)),
                                                 (*(long *)
                                                  ((char
                                                    *) (*(long *) ((char *)
                                                                   d +
                                                                   232)) +
                                                   56)), 2, 0, (char *) x_,
                                                 1220, 616, 32, 0);
    for (int i = 0; i < 8; i++) {
        char *p = z[i];
        int c = 0;
        while (*p != 4) {
            switch (*p) {
            case 0:
                k(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 1:
                r(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 2:
                u(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 3:
                e(i, p[1]
                  , p[2], 0, c);
                p += 3;
                break;
            case 5:
                p = z[p[1]];
                break;
            case 6:
                c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
                p += 2;
                break;
            }
        }
    }
    while (a++) {
        int f = syscall(2, s[1], 0);
        syscall(0, f, m, 380);
        syscall(3, f);
        for (int y = 0; y < 19; y++)
            for (int x = 0; x < 19; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    m[y][x] = 46;
        b(0, 2, 3, m[3][2], a & 1 ? 43 : 45);
        b(0, 2, 7, m[7][2], a & 2 ? 43 : 45);
        b(0, 2, 11, m[11][2], a & 4 ? 43 : 45);
        b(0, 2, 15, m[15][2], a & 8 ? 43 : 45);
        for (int i = 0; i < 20; i++)
            for (int y = 0; y < 19; y++)
                for (int x = 0; x < 19; x++)
                    if (m[y][x] == 62)
                        b(0, x + 1, y, m[y][x + 1],
                          !(m[y - 1][x] == 43 ? 1 : 0
                            || m[y + 1][x] == 43 ? 1 : 0) ? 43 : 45);
        for (int y = 0; y < 616; y++)
            for (int x = 0; x < 1220; x++)
                x_[y][x] = 0;
        for (int y = 0; y < 19; y++)
            for (int x = 0; x < 19; x++)
                d_(((m[y][x] >> 4) & 1) << 2 | (m[y][x] & 3), x, y);
        for (int y = 0; y < 19; y++)
            for (int x = 0; x < 19; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    d_(7, x, y);
        for (int y = 0; y < 616; y++)
            for (int x = 0; x < 1220; x++) {
                x_[y][x] &= 14737632 | (31 << ((x % 3) << 3));
                x_[y][x] += 986895 & (rn *= 16777619);
            } ((long (*)()) dlsym(T, _n + (4 * 20))) (d, w,
                                                      (*(long *)
                                                       ((char
                                                         *) (*(long
                                                               *) ((char *)
                                                                   d +
                                                                   232)) +
                                                        72)), M, 0, 0, 0,
                                                      0, 1220, 616);
        ((long (*)()) dlsym(T, _n + (5 * 20))) (d, w);
        ((long (*)()) dlsym(T, _n + (6 * 20))) (d);
        syscall(35, &N, &R);
    } return 0;
}

Что ж, по крайней мере одно из условий конкурса мы выполнили, код после препроцессора понятнее не стал.

Начнем с того, что можно выловить с первого взгляда и попытаемся восстановить цепочку событий:

dlsym\dlopen


Очевидно, что чтобы воспользоваться функциями X-сервера и создать окно, а затем в нем что-то отрисовать код должен обратиться к библиотеке XLib. В коде присутствуют функции dlopen/dlsym, позволяющие динамически подгрузить библиотеку, однако на вход им подается какая-то хитрая каша:

char _n[] =
    "pu~D--2os" "<<<<<<<<" "<<<DSlyrXuolp}e" "<<<<<<<<"
    "D_ny}hyOuqlpyKurxsk<D_ny" "}hyUq}{y" "<<<<<<<<" "DLihUq}{y" "<<<<<<<<"
    "<<<DQ}lKurxsk" "<<<<<<<<" "<<DZpiot<";
...
T = dlopen(_n, 2);

Пройдем на шаг назад и проинспектируем следующий код:
int h = 127;
    while (h--) {
        _n[h] ^= 28;
        _n[h] -= (_n[h] == 32 ? 32 : 0);
    }

Судя по всему, он некоторым образом преобразует исходный массив, позволяя нам получить читаемые строки. Выполним его отдельно:
https://onlinegdb.com/SJNM9Og7v:
libX11.so
XOpenDisplay
XCreateSimpleWindow
XCreateImage
XPutImage
XMapWindow
XFlush

Для того, чтобы одной строкой вызывать столь различные по формату функции код эксплуатирует тот факт, что в стандарте языка С (void) означает отсутствие параметров, а () — любое число параметров. Остается только привести полученный void * к соответствующему ((long (*)()) типу и вуаля:
w = ((long (*)()) dlsym(T, _n + (2 * 20))) (d, (*(long *)((char *) (*(long *)((char *) d + 232)) + 16))

Зная, что эти преобразования означают теперь мы можем заменить столь необычное использование dlsym сначала на строки:
После замены строк:
int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };

extern void *dlsym(void *, char *);
int x_[616][1220];
extern long syscall(long, ...);
extern void *dlopen(char *, int);
char m[19][20];
long w, N[2] = { 0, 1 << 29 };
int rn = 2166136261, _[8][40][64] = { 0 };
long R[2];
void *M, *d, *T;

void b(int t, int x, int y, int c, int l) {
    if ((x >= 19 || y >= 19 || x < 0 || y < 0) || (m[y][x] == l)
        || (m[y][x] != c))
        return;
    m[y][x] = l;
    b(t, x - 1, y, c, l);
    b(t, x + 1, y, c, l);
    b(t, x, y - 1, c, l);
    b(t, x, y + 1, c, l);
}

void e(int t, int x, int y, int c, int l) {
    if ((x >= 64 || y >= 40 || x < 0 || y < 0) || (_[t][y][x] == l)
        || (_[t][y][x] != c))
        return;
    _[t][y][x] = l;
    e(t, x - 1, y, c, l);
    e(t, x + 1, y, c, l);
    e(t, x, y - 1, c, l);
    e(t, x, y + 1, c, l);
}

void k(int t, int x, int y, int c, int l) {
    while (c--) {
        _[t][y][x++] = l;
        _[t][y++][x++] = l;
    }
}

void r(int t, int x, int y, int c, int l) {
    while (c--) {
        _[t][y][x--] = l;
        _[t][y++][x--] = l;
    }
}

void u(int t, int x, int y, int c, int l) {
    while (c--)
        _[t][y++][x] = l;
}

char *z[8] = { 
    (char[]) {4}, 
    (char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
                     21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
                     63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
                     32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
                     21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
                     36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
                     3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
        (char[]) {5, 1}, 
        (char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
                                   0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
                                   21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
                                   4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
                                   5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
                                   63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
                                   21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
                                   0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
                                   3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
                                   38 - 0,
                                   4},
        (char[]) {4}, (char[]) {4},
        (char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
                  21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
                  21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
                  16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
                  2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
                  3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
                  3, 30, 38 - 3, 4}, 
    (char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
                                               0, 8 + 0 + 0, 21, 12 - 0, 1,
                                               31, 9 + 0, 12 - 0, 1,
                                               55 - 0 - 0, 21, 12 - 0, 0,
                                               32, 9 + 3, 12 - 3, 0,
                                               8 + 3 + 3, 21, 12 - 3, 1,
                                               31, 9 + 3, 12 - 3, 1,
                                               55 - 3 - 3, 21, 12 - 3, 6,
                                               14 + 0, 2, 31 + 0, 13, 4,
                                               1 - 0, 31 + 0, 16, 7, 3,
                                               30 + 3 * 0, 14, 6,
                                               12 + 0 * 4, 3, 32 - 0,
                                               11 + 0 * 8, 6, 14 + 1, 2,
                                               31 + 1, 13, 4, 1 - 1,
                                               31 + 1, 16, 7, 3,
                                               30 + 3 * 1, 14, 6,
                                               12 + 1 * 4, 3, 32 - 1,
                                               11 + 1 * 8,
                                               4}
};

void d_(int t, int p, int q) {
    for (int y = 0; y < 40; y++)
        for (int x = 0; x < 64; x++)
            if (_[t]
                [y][x])
                x_[y + q * 16 + p * 16][x + 580 + p * 32 - q *
                                        32] = _[t][y][x];
}

int main(int a, char *s[]) {
    T = dlopen("libX11.so", 2);
    d = ((void *(*)()) dlsym(T, "XOpenDisplay") (0);
    w = ((long (*)()) dlsym(T, "XCreateSimpleWindow")) (d,
                                                (*(long *)
                                                 ((char
                                                   *) (*(long *) ((char *)
                                                                  d +
                                                                  232)) +
                                                  16))



                                                , 0, 0, 1220, 616, 1, 0,
                                                0);
    M = ((void *(*)()) dlsym(T, "XCreateImage")) (d,
                                                 (*(long *)
                                                  ((char
                                                    *) (*(long *) ((char *)
                                                                   d +
                                                                   232)) +
                                                   64)),
                                                 (*(long *)
                                                  ((char
                                                    *) (*(long *) ((char *)
                                                                   d +
                                                                   232)) +
                                                   56)), 2, 0, (char *) x_,
                                                 1220, 616, 32, 0);
    for (int i = 0; i < 8; i++) {
        char *p = z[i];
        int c = 0;
        while (*p != 4) {
            switch (*p) {
            case 0:
                k(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 1:
                r(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 2:
                u(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 3:
                e(i, p[1]
                  , p[2], 0, c);
                p += 3;
                break;
            case 5:
                p = z[p[1]];
                break;
            case 6:
                c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
                p += 2;
                break;
            }
        }
    }
    while (a++) {
        int f = syscall(2, s[1], 0);
        syscall(0, f, m, 380);
        syscall(3, f);
        for (int y = 0; y < 19; y++)
            for (int x = 0; x < 19; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    m[y][x] = 46;
        b(0, 2, 3, m[3][2], a & 1 ? 43 : 45);
        b(0, 2, 7, m[7][2], a & 2 ? 43 : 45);
        b(0, 2, 11, m[11][2], a & 4 ? 43 : 45);
        b(0, 2, 15, m[15][2], a & 8 ? 43 : 45);
        for (int i = 0; i < 20; i++)
            for (int y = 0; y < 19; y++)
                for (int x = 0; x < 19; x++)
                    if (m[y][x] == 62)
                        b(0, x + 1, y, m[y][x + 1],
                          !(m[y - 1][x] == 43 ? 1 : 0
                            || m[y + 1][x] == 43 ? 1 : 0) ? 43 : 45);
        for (int y = 0; y < 616; y++)
            for (int x = 0; x < 1220; x++)
                x_[y][x] = 0;
        for (int y = 0; y < 19; y++)
            for (int x = 0; x < 19; x++)
                d_(((m[y][x] >> 4) & 1) << 2 | (m[y][x] & 3), x, y);
        for (int y = 0; y < 19; y++)
            for (int x = 0; x < 19; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    d_(7, x, y);
        for (int y = 0; y < 616; y++)
            for (int x = 0; x < 1220; x++) {
                x_[y][x] &= 14737632 | (31 << ((x % 3) << 3));
                x_[y][x] += 986895 & (rn *= 16777619);
            } ((long (*)()) dlsym(T, "XPutImage")) (d, w,
                                                      (*(long *)
                                                       ((char
                                                         *) (*(long
                                                               *) ((char *)
                                                                   d +
                                                                   232)) +
                                                        72)), M, 0, 0, 0,
                                                      0, 1220, 616);
        ((long (*)()) dlsym(T, "XMapWindow")) (d, w);
        ((long (*)()) dlsym(T, "XFlush")) (d);
        syscall(35, &N, &R);
    } return 0;
}


А потом и на родные функции:
После замены на ''родные'' функции:
#include <X11/Xlib.h>

int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };

int x_[616][1220];
extern long syscall(long, ...);
char m[19][20];
long w, N[2] = { 0, 1 << 29 };
int rn = 2166136261, _[8][40][64] = { 0 };
long R[2];
void *M, *d, *T;

void b(int t, int x, int y, int c, int l) {
    if ((x >= 19 || y >= 19 || x < 0 || y < 0) || (m[y][x] == l)
        || (m[y][x] != c))
        return;
    m[y][x] = l;
    b(t, x - 1, y, c, l);
    b(t, x + 1, y, c, l);
    b(t, x, y - 1, c, l);
    b(t, x, y + 1, c, l);
}

void e(int t, int x, int y, int c, int l) {
    if ((x >= 64 || y >= 40 || x < 0 || y < 0) || (_[t][y][x] == l)
        || (_[t][y][x] != c))
        return;
    _[t][y][x] = l;
    e(t, x - 1, y, c, l);
    e(t, x + 1, y, c, l);
    e(t, x, y - 1, c, l);
    e(t, x, y + 1, c, l);
}

void k(int t, int x, int y, int c, int l) {
    while (c--) {
        _[t][y][x++] = l;
        _[t][y++][x++] = l;
    }
}

void r(int t, int x, int y, int c, int l) {
    while (c--) {
        _[t][y][x--] = l;
        _[t][y++][x--] = l;
    }
}

void u(int t, int x, int y, int c, int l) {
    while (c--)
        _[t][y++][x] = l;
}

char *z[8] = { 
    (char[]) {4}, 
    (char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
                     21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
                     63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
                     32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
                     21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
                     36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
                     3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
        (char[]) {5, 1}, 
        (char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
                                   0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
                                   21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
                                   4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
                                   5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
                                   63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
                                   21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
                                   0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
                                   3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
                                   38 - 0,
                                   4},
        (char[]) {4}, (char[]) {4},
        (char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
                  21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
                  21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
                  16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
                  2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
                  3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
                  3, 30, 38 - 3, 4}, 
    (char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
                                               0, 8 + 0 + 0, 21, 12 - 0, 1,
                                               31, 9 + 0, 12 - 0, 1,
                                               55 - 0 - 0, 21, 12 - 0, 0,
                                               32, 9 + 3, 12 - 3, 0,
                                               8 + 3 + 3, 21, 12 - 3, 1,
                                               31, 9 + 3, 12 - 3, 1,
                                               55 - 3 - 3, 21, 12 - 3, 6,
                                               14 + 0, 2, 31 + 0, 13, 4,
                                               1 - 0, 31 + 0, 16, 7, 3,
                                               30 + 3 * 0, 14, 6,
                                               12 + 0 * 4, 3, 32 - 0,
                                               11 + 0 * 8, 6, 14 + 1, 2,
                                               31 + 1, 13, 4, 1 - 1,
                                               31 + 1, 16, 7, 3,
                                               30 + 3 * 1, 14, 6,
                                               12 + 1 * 4, 3, 32 - 1,
                                               11 + 1 * 8,
                                               4}
};

void d_(int t, int p, int q) {
    for (int y = 0; y < 40; y++)
        for (int x = 0; x < 64; x++)
            if (_[t]
                [y][x])
                x_[y + q * 16 + p * 16][x + 580 + p * 32 - q *
                                        32] = _[t][y][x];
}

int main(int a, char *s[]) {
    d = XOpenDisplay(0);
    w = XCreateSimpleWindow(d, (*(long *) ((char *) (*(long *) ((char *)d + 232)) + 16)), 0, 0, 1220, 616, 1, 0, 0);
    M = XCreateImage(d, (*(long *)((char *) (*(long *) ((char *)d + 232)) + 64)), (*(long *)((char *) (*(long *) ((char *)d + 232)) + 56)), 2, 0, (char *) x_, 1220, 616, 32, 0);
    for (int i = 0; i < 8; i++) {
            char *p = z[i];
            int c = 0;
            while (*p != 4) {
                switch (*p) {
                case 0:
                    k(i, p[1], p[2], p[3], c);
                    p += 4;
                    break;
                case 1:
                    r(i, p[1], p[2], p[3], c);
                    p += 4;
                    break;
                case 2:
                    u(i, p[1], p[2], p[3], c);
                    p += 4;
                    break;
                case 3:
                    e(i, p[1]
                      , p[2], 0, c);
                    p += 3;
                    break;
                case 5:
                    p = z[p[1]];
                    break;
                case 6:
                    c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
                    p += 2;
                    break;
                }
            }
    }
    while (a++) {
            int f = syscall(2, s[1], 0);
            syscall(0, f, m, 380);
            syscall(3, f);
            for (int y = 0; y < 19; y++)
                for (int x = 0; x < 19; x++)
                    if ((x % 14 == 2) && (y % 4 == 3))
                        m[y][x] = 46;
            b(0, 2, 3, m[3][2], a & 1 ? 43 : 45);
            b(0, 2, 7, m[7][2], a & 2 ? 43 : 45);
            b(0, 2, 11, m[11][2], a & 4 ? 43 : 45);
            b(0, 2, 15, m[15][2], a & 8 ? 43 : 45);
            for (int i = 0; i < 20; i++)
                for (int y = 0; y < 19; y++)
                    for (int x = 0; x < 19; x++)
                        if (m[y][x] == 62)
                            b(0, x + 1, y, m[y][x + 1],
                            !(m[y - 1][x] == 43 ? 1 : 0
                                || m[y + 1][x] == 43 ? 1 : 0) ? 43 : 45);
            for (int y = 0; y < 616; y++)
                for (int x = 0; x < 1220; x++)
                    x_[y][x] = 0;
            for (int y = 0; y < 19; y++)
                for (int x = 0; x < 19; x++)
                    d_(((m[y][x] >> 4) & 1) << 2 | (m[y][x] & 3), x, y);
            for (int y = 0; y < 19; y++)
                for (int x = 0; x < 19; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    d_(7, x, y);
        for (int y = 0; y < 616; y++)
                for (int x = 0; x < 1220; x++) {
                    x_[y][x] &= 14737632 | (31 << ((x % 3) << 3));
                    x_[y][x] += 986895 & (rn *= 16777619);
                }
            XPutImage(d, w, (*(long *)((char *) (*(long *) ((char *)d + 232)) + 72)), M, 0, 0, 0, 0, 1220, 616);
            XMapWindow(d, w);
            XFlush(d);
            syscall(35, &N, &R);
    } 
    return 0;
}

Syscalls


Заменим системные вызовы по тому же принципу, которому мы следовали в первой части:
Код без системных вызовов:
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };

int x_[616][1220];
char m[19][20];
long w;
int rn = 2166136261, _[8][40][64] = { 0 };

void *M, *d, *T;

void b(int t, int x, int y, int c, int l) {
    if ((x >= 19 || y >= 19 || x < 0 || y < 0) || (m[y][x] == l)
        || (m[y][x] != c))
        return;
    m[y][x] = l;
    b(t, x - 1, y, c, l);
    b(t, x + 1, y, c, l);
    b(t, x, y - 1, c, l);
    b(t, x, y + 1, c, l);
}

void e(int t, int x, int y, int c, int l) {
    if ((x >= 64 || y >= 40 || x < 0 || y < 0) || (_[t][y][x] == l)
        || (_[t][y][x] != c))
        return;
    _[t][y][x] = l;
    e(t, x - 1, y, c, l);
    e(t, x + 1, y, c, l);
    e(t, x, y - 1, c, l);
    e(t, x, y + 1, c, l);
}

void k(int t, int x, int y, int c, int l) {
    while (c--) {
        _[t][y][x++] = l;
        _[t][y++][x++] = l;
    }
}

void r(int t, int x, int y, int c, int l) {
    while (c--) {
        _[t][y][x--] = l;
        _[t][y++][x--] = l;
    }
}

void u(int t, int x, int y, int c, int l) {
    while (c--)
        _[t][y++][x] = l;
}

char *z[8] = { 
    (char[]) {4}, 
    (char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
                     21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
                     63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
                     32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
                     21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
                     36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
                     3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
        (char[]) {5, 1}, 
        (char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
                                   0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
                                   21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
                                   4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
                                   5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
                                   63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
                                   21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
                                   0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
                                   3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
                                   38 - 0,
                                   4},
        (char[]) {4}, (char[]) {4},
        (char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
                  21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
                  21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
                  16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
                  2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
                  3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
                  3, 30, 38 - 3, 4}, 
    (char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
                                               0, 8 + 0 + 0, 21, 12 - 0, 1,
                                               31, 9 + 0, 12 - 0, 1,
                                               55 - 0 - 0, 21, 12 - 0, 0,
                                               32, 9 + 3, 12 - 3, 0,
                                               8 + 3 + 3, 21, 12 - 3, 1,
                                               31, 9 + 3, 12 - 3, 1,
                                               55 - 3 - 3, 21, 12 - 3, 6,
                                               14 + 0, 2, 31 + 0, 13, 4,
                                               1 - 0, 31 + 0, 16, 7, 3,
                                               30 + 3 * 0, 14, 6,
                                               12 + 0 * 4, 3, 32 - 0,
                                               11 + 0 * 8, 6, 14 + 1, 2,
                                               31 + 1, 13, 4, 1 - 1,
                                               31 + 1, 16, 7, 3,
                                               30 + 3 * 1, 14, 6,
                                               12 + 1 * 4, 3, 32 - 1,
                                               11 + 1 * 8,
                                               4}
};

void d_(int t, int p, int q) {
    for (int y = 0; y < 40; y++)
        for (int x = 0; x < 64; x++)
            if (_[t]
                [y][x])
                x_[y + q * 16 + p * 16][x + 580 + p * 32 - q *
                                        32] = _[t][y][x];
}

int main(int a, char *s[]) {
    d = XOpenDisplay(0);
    w = XCreateSimpleWindow(d, (*(long *) ((char *) (*(long *) ((char *)d + 232)) + 16)), 0, 0, 1220, 616, 1, 0, 0);
    M = XCreateImage(d, (*(long *)((char *) (*(long *) ((char *)d + 232)) + 64)), (*(long *)((char *) (*(long *) ((char *)d + 232)) + 56)), 2, 0, (char *) x_, 1220, 616, 32, 0);
    for (int i = 0; i < 8; i++) {
            char *p = z[i];
            int c = 0;
            while (*p != 4) {
                switch (*p) {
                case 0:
                    k(i, p[1], p[2], p[3], c);
                    p += 4;
                    break;
                case 1:
                    r(i, p[1], p[2], p[3], c);
                    p += 4;
                    break;
                case 2:
                    u(i, p[1], p[2], p[3], c);
                    p += 4;
                    break;
                case 3:
                    e(i, p[1]
                      , p[2], 0, c);
                    p += 3;
                    break;
                case 5:
                    p = z[p[1]];
                    break;
                case 6:
                    c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
                    p += 2;
                    break;
                }
            }
    }
    while (a++) {
            int f = open(s[1], 0);
            read(f, m, 380);
            close(f);
            
            
            for (int y = 0; y < 19; y++)
                for (int x = 0; x < 19; x++)
                    if ((x % 14 == 2) && (y % 4 == 3))
                        m[y][x] = 46;
            b(0, 2, 3, m[3][2], a & 1 ? 43 : 45);
            b(0, 2, 7, m[7][2], a & 2 ? 43 : 45);
            b(0, 2, 11, m[11][2], a & 4 ? 43 : 45);
            b(0, 2, 15, m[15][2], a & 8 ? 43 : 45);
            for (int i = 0; i < 20; i++)
                for (int y = 0; y < 19; y++)
                    for (int x = 0; x < 19; x++)
                        if (m[y][x] == 62)
                            b(0, x + 1, y, m[y][x + 1],
                            !(m[y - 1][x] == 43 ? 1 : 0
                                || m[y + 1][x] == 43 ? 1 : 0) ? 43 : 45);
            for (int y = 0; y < 616; y++)
                for (int x = 0; x < 1220; x++)
                    x_[y][x] = 0;
            for (int y = 0; y < 19; y++)
                for (int x = 0; x < 19; x++)
                    d_(((m[y][x] >> 4) & 1) << 2 | (m[y][x] & 3), x, y);
            for (int y = 0; y < 19; y++)
                for (int x = 0; x < 19; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    d_(7, x, y);
        for (int y = 0; y < 616; y++)
                for (int x = 0; x < 1220; x++) {
                    x_[y][x] &= 14737632 | (31 << ((x % 3) << 3));
                    x_[y][x] += 986895 & (rn *= 16777619);
                }
            XPutImage(d, w, (*(long *)((char *) (*(long *) ((char *)d + 232)) + 72)), M, 0, 0, 0, 0, 1220, 616);
            XMapWindow(d, w);
            XFlush(d);
            
            sleep(1);
    } 
    return 0;
}


XCreateSimpleWindow и смещения


Постараемся разобрать следующую конструкцию:
w = XCreateSimpleWindow(d, (*(long *) ((char *) (*(long *) ((char *)d + 232)) + 16)), 0, 0, 1220, 616, 1, 0, 0);

Куча преобразований типов, которые, на первый взгляд, нужны лишь чтобы запутать читателя, однако каждое преобразование здесь имеет свою цель, а именно:
d — это указатель на структуру Display в контексте Xlib. Он имеет поле-массив, называемое screens и для того, чтобы получить указатель на первый элемент этого массива мы должны отсчитать некоторое количество байт (на x64 — 232) от указателя на Display вперед. Так как Display не char *, то при прямом отсчитывании мы обсчитались бы в sizeof(long *) байт. Поэтому приведем d к char * и сдвинемся на 232 байта:
 ((char *)d + 232)

Мы получили позицию первого элемента Screens в памяти. Приведем его к полноценному указателю и разыменуем:
(*(long *) ((char *)d + 232))

Теперь внутри структуры Screens мы должны получить указатель на корневое окно, Root. Для этого отойдем от Screens на 16 байт и разыменуем конструкцию:
(*(long *) ((char *) (*(long *) ((char *)d + 232)) + 16))

Эта конструкция на самом деле каждый день используется программистами под Xlib, поскольку её общеупотребимый эквивалент — это
RootWindow(Display, DefaultScreen(Display))

Аналогичным образом заменим соответствующие смещения в других местах, чтобы получить более привычные глазу макросы (заодно поправим косяки indent):
Код после замены смещений:

#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };

int x_[616][1220];
char m[19][20];
int rn = 2166136261, _[8][40][64] = { 0 };

void *T;

Display * display;
Window window;
XImage * image;

void b(int t, int x, int y, int c, int l) {
    if ((x >= 19 || y >= 19 || x < 0 || y < 0) || (m[y][x] == l)
    || (m[y][x] != c))
    return;
    m[y][x] = l;
    b(t, x - 1, y, c, l);
    b(t, x + 1, y, c, l);
    b(t, x, y - 1, c, l);
    b(t, x, y + 1, c, l);
}

void e(int t, int x, int y, int c, int l) {
    if ((x >= 64 || y >= 40 || x < 0 || y < 0) || (_[t][y][x] == l)
        || (_[t][y][x] != c))
        return;
    _[t][y][x] = l;
    e(t, x - 1, y, c, l);
    e(t, x + 1, y, c, l);
    e(t, x, y - 1, c, l);
    e(t, x, y + 1, c, l);
}

void k(int t, int x, int y, int c, int l) {
    while (c--) {
        _[t][y][x++] = l;
        _[t][y++][x++] = l;
    }
}

void r(int t, int x, int y, int c, int l) {
    while (c--) {
        _[t][y][x--] = l;
        _[t][y++][x--] = l;
    }
}

void u(int t, int x, int y, int c, int l) {
    while (c--)
        _[t][y++][x] = l;
}

char *z[8] = { 
    (char[]) {4}, 
    (char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
              21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
              63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
              32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
              21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
              36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
              3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
    (char[]) {5, 1}, 
    (char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
              0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
              21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
              4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
              5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
              63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
              21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
              0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
              3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
              38 - 0,
              4},
    (char[]) {4}, 
    (char[]) {4},
    (char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
              21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
              21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
              16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
              2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
              3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
              3, 30, 38 - 3, 4}, 
    (char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
              0, 8 + 0 + 0, 21, 12 - 0, 1,
              31, 9 + 0, 12 - 0, 1,
              55 - 0 - 0, 21, 12 - 0, 0,
              32, 9 + 3, 12 - 3, 0,
              8 + 3 + 3, 21, 12 - 3, 1,
              31, 9 + 3, 12 - 3, 1,
              55 - 3 - 3, 21, 12 - 3, 6,
              14 + 0, 2, 31 + 0, 13, 4,
              1 - 0, 31 + 0, 16, 7, 3,
              30 + 3 * 0, 14, 6,
              12 + 0 * 4, 3, 32 - 0,
              11 + 0 * 8, 6, 14 + 1, 2,
              31 + 1, 13, 4, 1 - 1,
              31 + 1, 16, 7, 3,
              30 + 3 * 1, 14, 6,
              12 + 1 * 4, 3, 32 - 1,
              11 + 1 * 8,
              4}
};

void d_(int t, int p, int q) {
    for (int y = 0; y < 40; y++)
    for (int x = 0; x < 64; x++)
        if (_[t][y][x])
            x_[y + q * 16 + p * 16][x + 580 + p * 32 - q * 32] = _[t][y][x];
}

int main(int a, char *s[]) {
    display = XOpenDisplay(0);
    window = XCreateSimpleWindow(display, 
                                 RootWindow(display, DefaultScreen(display)), 
                                 0, 0, 1220, 616, 1, 0, 0);
    image = XCreateImage(display, 
                     DefaultVisual(display, DefaultScreen(display)), 
                     DefaultDepth(display, DefaultScreen(display)),
                     2, 0, (char *) x_, 1220, 616, 32, 0);
    for (int i = 0; i < 8; i++) {
        char *p = z[i];
        int c = 0;
        while (*p != 4) {
            switch (*p) {
            case 0:
                k(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 1:
                r(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 2:
                u(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 3:
                e(i, p[1]
                  , p[2], 0, c);
                p += 3;
                break;
            case 5:
                p = z[p[1]];
                break;
            case 6:
                c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
                p += 2;
                break;
            }
        }
    }
    while (a++) {
        int f = open(s[1], 0);
        read(f, m, 380);
        close(f);
        
        
        for (int y = 0; y < 19; y++)
            for (int x = 0; x < 19; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    m[y][x] = 46;
        b(0, 2, 3, m[3][2], a & 1 ? 43 : 45);
        b(0, 2, 7, m[7][2], a & 2 ? 43 : 45);
        b(0, 2, 11, m[11][2], a & 4 ? 43 : 45);
        b(0, 2, 15, m[15][2], a & 8 ? 43 : 45);
        for (int i = 0; i < 20; i++)
            for (int y = 0; y < 19; y++)
                for (int x = 0; x < 19; x++)
                    if (m[y][x] == 62)
                        b(0, x + 1, y, m[y][x + 1],
                            !(m[y - 1][x] == 43 ? 1 : 0
                            || m[y + 1][x] == 43 ? 1 : 0) ? 43 : 45);
        for (int y = 0; y < 616; y++)
            for (int x = 0; x < 1220; x++)
                x_[y][x] = 0;
        for (int y = 0; y < 19; y++)
            for (int x = 0; x < 19; x++)
                d_(((m[y][x] >> 4) & 1) << 2 | (m[y][x] & 3), x, y);
        for (int y = 0; y < 19; y++)
            for (int x = 0; x < 19; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    d_(7, x, y);
        for (int y = 0; y < 616; y++)
            for (int x = 0; x < 1220; x++) {
                x_[y][x] &= 14737632 | (31 << ((x % 3) << 3));
                x_[y][x] += 986895 & (rn *= 16777619);
            }
        XPutImage(display, window, 
                  DefaultGC(display, DefaultScreen(display)), 
                  image, 0, 0, 0, 0, 1220, 616);
        XMapWindow(display, window);
        XFlush(display);
        
        sleep(1);
    } 
    return 0;
}


Данные изображения


Обратим внимание, что XCreateImage требует на вход указатель на область памяти, где будут храниться данные пикселей. Для нашего вызова функции это переменная «x_». Переименуем ее в pixdata и найдем все места, где она используется:
void d_(int t, int p, int q) {
    for (int y = 0; y < 40; y++)
    for (int x = 0; x < 64; x++)
        if (_[t][y][x])
            pixdata[y + q * 16 + p * 16][x + 580 + p * 32 - q * 32] = _[t][y][x]; // Очевидно, что это копирование данных из какого-то источника
}
    image = XCreateImage(display, 
                     DefaultVisual(display, DefaultScreen(display)), 
                     DefaultDepth(display, DefaultScreen(display)),
                     2, 0, (char *) pixdata, 1220, 616, 32, 0); // создание изображения
        for (int y = 0; y < 616; y++)
            for (int x = 0; x < 1220; x++)
                pixdata[y][x] = 0; // "Обнуление" пикселей, закраска черным цветом
        for (int y = 0; y < 616; y++)
            for (int x = 0; x < 1220; x++) { // Какая-то странная математическая операция, очевидно применяемая ко всему изображению.
                pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
                pixdata[y][x] += 986895 & (rn *= 16777619);
            }

Вычленим блок pixdata[..] = 0 в отдельную функцию и попытаемся разобрать, что же делает первое вхождение:
    for (int y = 0; y < 40; y++)
    for (int x = 0; x < 64; x++)
        if (_[t][y][x])
            pixdata[y + q * 16 + p * 16][x + 580 + p * 32 - q * 32] = _[t][y][x];

Если присмотреться к итоговому изображению, сформированному при работе программы, то легко заметить, что 40 и 64 — это размеры отдельного «блока», из которого построена схема.

Следовательно, эта функция рисует отдельный «тайл» на канве основного изображения, а судя по индексации массива "_" переменная «t» отвечает за индекс изображения, а p и q — за координаты x и y. Заодно переименуем "_" в textures:
Код на данный момент:

#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

/* Код после рефакторинга */

/*! \brief Ширина изображения в пикселях */
#define IMAGE_WIDTH *1220)
/*! \brief Высота изображения в пикселях */
#define IMAGE_HEIGHT (616)

/*! \brief Количество текстур */
#define TEXTURE_COUNT (8)
/*! \brief Ширина текстуры в пикселях */
#define TEXTURE_WIDTH (64)
/*! \brief Высота текстур в пикселях */
#define TEXTURE_HEIGHT (40)

/*! \brief Бинарные данные пикселей изображения.
 * Типизированы к int для оперирования пикселями вместо каналов */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };

/*! \brief Экземпляр дисплея Xlib */
Display * display;
/*! \brief Экземпляр главного окна Xlib */
Window window;
/*! \brief Изображение для вывода на экран */
XImage * image;

/* \brief Обнуляет изображение, заполняя его черным цветом */
static void _image_reset(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++)
            pixdata[y][x] = 0;
}

/*! \brief Отрисовывает текстуру на главном холсте по указанным координатам
 * \param[in] t Индекс текстуры
 * \param[in] x X координата тайла
 * \param[in] y Y координата тайла */
void _texture_draw(int t, int x, int y) {
    for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
        for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
            if (textures[t][ty][tx])
                pixdata[ty + y * 16 + x * 16]
                       [tx + 580 + x * 32 - y * 32] = textures[t][ty][tx];
}

/* Код до рефакторинга */

int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };

char m[19][20];
int rn = 2166136261;

void *T;

void b(int t, int x, int y, int c, int l) {
    if ((x >= 19 || y >= 19 || x < 0 || y < 0) || (m[y][x] == l)
    || (m[y][x] != c))
    return;
    m[y][x] = l;
    b(t, x - 1, y, c, l);
    b(t, x + 1, y, c, l);
    b(t, x, y - 1, c, l);
    b(t, x, y + 1, c, l);
}

void e(int t, int x, int y, int c, int l) {
    if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT || 
         x < 0 || y < 0) || 
         (textures[t][y][x] == l) || 
         (textures[t][y][x] != c))
        return;
    textures[t][y][x] = l;
    e(t, x - 1, y, c, l);
    e(t, x + 1, y, c, l);
    e(t, x, y - 1, c, l);
    e(t, x, y + 1, c, l);
}

void k(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x++] = l;
        textures[t][y++][x++] = l;
    }
}

void r(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x--] = l;
        textures[t][y++][x--] = l;
    }
}

void u(int t, int x, int y, int c, int l) {
    while (c--)
        textures[t][y++][x] = l;
}

char *z[8] = { 
    (char[]) {4}, 
    (char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
              21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
              63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
              32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
              21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
              36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
              3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
    (char[]) {5, 1}, 
    (char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
              0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
              21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
              4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
              5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
              63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
              21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
              0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
              3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
              38 - 0,
              4},
    (char[]) {4}, 
    (char[]) {4},
    (char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
              21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
              21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
              16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
              2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
              3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
              3, 30, 38 - 3, 4}, 
    (char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
              0, 8 + 0 + 0, 21, 12 - 0, 1,
              31, 9 + 0, 12 - 0, 1,
              55 - 0 - 0, 21, 12 - 0, 0,
              32, 9 + 3, 12 - 3, 0,
              8 + 3 + 3, 21, 12 - 3, 1,
              31, 9 + 3, 12 - 3, 1,
              55 - 3 - 3, 21, 12 - 3, 6,
              14 + 0, 2, 31 + 0, 13, 4,
              1 - 0, 31 + 0, 16, 7, 3,
              30 + 3 * 0, 14, 6,
              12 + 0 * 4, 3, 32 - 0,
              11 + 0 * 8, 6, 14 + 1, 2,
              31 + 1, 13, 4, 1 - 1,
              31 + 1, 16, 7, 3,
              30 + 3 * 1, 14, 6,
              12 + 1 * 4, 3, 32 - 1,
              11 + 1 * 8,
              4}
};

int main(int a, char *s[]) {
    display = XOpenDisplay(0);
    window = XCreateSimpleWindow(display, 
                                 RootWindow(display, DefaultScreen(display)), 
                                 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
    image = XCreateImage(display, 
                     DefaultVisual(display, DefaultScreen(display)), 
                     DefaultDepth(display, DefaultScreen(display)),
                     2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
    for (int i = 0; i < 8; i++) {
        char *p = z[i];
        int c = 0;
        while (*p != 4) {
            switch (*p) {
            case 0:
                k(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 1:
                r(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 2:
                u(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 3:
                e(i, p[1]
                  , p[2], 0, c);
                p += 3;
                break;
            case 5:
                p = z[p[1]];
                break;
            case 6:
                c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
                p += 2;
                break;
            }
        }
    }
    while (a++) {
        int f = open(s[1], 0);
        read(f, m, 380);
        close(f);
        
        for (int y = 0; y < 19; y++)
            for (int x = 0; x < 19; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    m[y][x] = 46;
        b(0, 2, 3, m[3][2], a & 1 ? 43 : 45);
        b(0, 2, 7, m[7][2], a & 2 ? 43 : 45);
        b(0, 2, 11, m[11][2], a & 4 ? 43 : 45);
        b(0, 2, 15, m[15][2], a & 8 ? 43 : 45);
        for (int i = 0; i < 20; i++)
            for (int y = 0; y < 19; y++)
                for (int x = 0; x < 19; x++)
                    if (m[y][x] == 62)
                        b(0, x + 1, y, m[y][x + 1],
                            !(m[y - 1][x] == 43 ? 1 : 0
                            || m[y + 1][x] == 43 ? 1 : 0) ? 43 : 45);
        
        _image_reset();  
        
        for (int y = 0; y < 19; y++)
            for (int x = 0; x < 19; x++)
                _texture_draw(((m[y][x] >> 4) & 1) << 2 | (m[y][x] & 3), x, y);
                
        for (int y = 0; y < 19; y++)
            for (int x = 0; x < 19; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    _texture_draw(7, x, y);
        for (int y = 0; y < IMAGE_HEIGHT; y++)
            for (int x = 0; x < IMAGE_WIDTH; x++) {
                pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
                pixdata[y][x] += 986895 & (rn *= 16777619);
            }
        XPutImage(display, window, 
                  DefaultGC(display, DefaultScreen(display)), 
                  image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
        XMapWindow(display, window);
        XFlush(display);
        
        sleep(1);
    } 
    return 0;
}


Чтение карты


Выделим в отдельную функцию строки open..close, где читается содержимое выбранного файла в переменную m (которую переименуем в mapdata).
Почему файл считается в каждом цикле? Так было короче с точки зрения кода и токенов. Около 4 дней занял процесс «утрамбовывания» кода чтобы поместиться в лимиты правил. Если читать файл только один раз то потребовалось бы дополнительное хранилище и какой-то аналог функции memcpy.

Выделена функция _map_read
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

/* Код после рефакторинга */

/*! \brief Ширина изображения в пикселях */
#define IMAGE_WIDTH (1220)
/*! \brief Высота изображения в пикселях */
#define IMAGE_HEIGHT (616)
/*! \brief Сдвиг верхней грани карты от левой стороны */
#define IMAGE_SHIFTX (580)

/*! \brief Количество текстур */
#define TEXTURE_COUNT (8)
/*! \brief Ширина текстуры в пикселях */
#define TEXTURE_WIDTH (64)
/*! \brief Высота текстур в пикселях */
#define TEXTURE_HEIGHT (40)
/*! \brief Ширина грани текстуры в пикселях */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief Высота грани текстуры в пикселях */
#define TEXTURE_TOP_HEIGHT (32)

/*! \brief Ширина эмулируемого поля */
#define MAP_WIDTH (19)
/*! \brief Высота эмулируемого поля */
#define MAP_HEIGHT (19)
/*! \brief Количество данные в файле-чертеже. Один байт добавлен для символа '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)

/*! \brief Бинарные данные пикселей изображения.
 * Типизированы к int для оперирования пикселями вместо каналов */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief Текстуры блоков, отображаемых на поле */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief Данные эмулируемого поля. 
 * Один байт добавлен для упрощения обработки символа '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];

/*! \brief Экземпляр дисплея Xlib */
Display * display;
/*! \brief Экземпляр главного окна Xlib */
Window window;
/*! \brief Изображение для вывода на экран */
XImage * image;

/* \brief Обнуляет изображение, заполняя его черным цветом */
static void _image_reset(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++)
            pixdata[y][x] = 0;
}

/*! \brief Отрисовывает текстуру на главном холсте по указанным координатам
 * \param[in] t Индекс текстуры
 * \param[in] x X координата тайла
 * \param[in] y Y координата тайла */
static void _texture_draw(int t, int x, int y) {
    for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
        for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
            if (textures[t][ty][tx])
                pixdata[ty + 
                        y * (TEXTURE_TOP_HEIGHT / 2) + 
                        x * (TEXTURE_TOP_HEIGHT / 2)]
                       [tx + 
                        IMAGE_SHIFTX + 
                        x * (TEXTURE_TOP_WIDTH / 2) - 
                        y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}

/*! \brief Читает данные файла-чертежа и загружает их в карту 
 * \param[in] filename Имя файла-чертежа */
static void _map_read(const char * filename) {
    int f = open(filename, 0);
    read(f, mapdata, MAP_FILEDATA);
    close(f);
}

/* Код до рефакторинга */

int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
int rn = 2166136261;

void *T;

void b(int t, int x, int y, int c, int l) {
    if ((x >= MAP_WIDTH || y >= MAP_HEIGHT || 
         x < 0 || y < 0) || (mapdata[y][x] == l)
        || (mapdata[y][x] != c))
        return;
    mapdata[y][x] = l;
    b(t, x - 1, y, c, l);
    b(t, x + 1, y, c, l);
    b(t, x, y - 1, c, l);
    b(t, x, y + 1, c, l);
}

void e(int t, int x, int y, int c, int l) {
    if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT || 
         x < 0 || y < 0) || 
         (textures[t][y][x] == l) || 
         (textures[t][y][x] != c))
        return;
    textures[t][y][x] = l;
    e(t, x - 1, y, c, l);
    e(t, x + 1, y, c, l);
    e(t, x, y - 1, c, l);
    e(t, x, y + 1, c, l);
}

void k(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x++] = l;
        textures[t][y++][x++] = l;
    }
}

void r(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x--] = l;
        textures[t][y++][x--] = l;
    }
}

void u(int t, int x, int y, int c, int l) {
    while (c--)
        textures[t][y++][x] = l;
}

char *z[8] = { 
    (char[]) {4}, 
    (char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
              21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
              63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
              32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
              21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
              36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
              3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
    (char[]) {5, 1}, 
    (char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
              0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
              21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
              4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
              5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
              63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
              21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
              0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
              3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
              38 - 0,
              4},
    (char[]) {4}, 
    (char[]) {4},
    (char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
              21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
              21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
              16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
              2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
              3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
              3, 30, 38 - 3, 4}, 
    (char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
              0, 8 + 0 + 0, 21, 12 - 0, 1,
              31, 9 + 0, 12 - 0, 1,
              55 - 0 - 0, 21, 12 - 0, 0,
              32, 9 + 3, 12 - 3, 0,
              8 + 3 + 3, 21, 12 - 3, 1,
              31, 9 + 3, 12 - 3, 1,
              55 - 3 - 3, 21, 12 - 3, 6,
              14 + 0, 2, 31 + 0, 13, 4,
              1 - 0, 31 + 0, 16, 7, 3,
              30 + 3 * 0, 14, 6,
              12 + 0 * 4, 3, 32 - 0,
              11 + 0 * 8, 6, 14 + 1, 2,
              31 + 1, 13, 4, 1 - 1,
              31 + 1, 16, 7, 3,
              30 + 3 * 1, 14, 6,
              12 + 1 * 4, 3, 32 - 1,
              11 + 1 * 8,
              4}
};

int main(int a, char *s[]) {
    display = XOpenDisplay(0);
    window = XCreateSimpleWindow(display, 
                                 RootWindow(display, DefaultScreen(display)), 
                                 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
    image = XCreateImage(display, 
                     DefaultVisual(display, DefaultScreen(display)), 
                     DefaultDepth(display, DefaultScreen(display)),
                     2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
    for (int i = 0; i < 8; i++) {
        char *p = z[i];
        int c = 0;
        while (*p != 4) {
            switch (*p) {
            case 0:
                k(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 1:
                r(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 2:
                u(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 3:
                e(i, p[1]
                  , p[2], 0, c);
                p += 3;
                break;
            case 5:
                p = z[p[1]];
                break;
            case 6:
                c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
                p += 2;
                break;
            }
        }
    }
    while (a++) {
        _map_read(s[1]);
        
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    mapdata[y][x] = 46;
        b(0, 2, 3, mapdata[3][2], a & 1 ? 43 : 45);
        b(0, 2, 7, mapdata[7][2], a & 2 ? 43 : 45);
        b(0, 2, 11, mapdata[11][2], a & 4 ? 43 : 45);
        b(0, 2, 15, mapdata[15][2], a & 8 ? 43 : 45);
        for (int i = 0; i < 20; i++)
            for (int y = 0; y < MAP_HEIGHT; y++)
                for (int x = 0; x < MAP_WIDTH; x++)
                    if (mapdata[y][x] == 62)
                        b(0, x + 1, y, mapdata[y][x + 1],
                            !(mapdata[y - 1][x] == 43 ? 1 : 0
                            || mapdata[y + 1][x] == 43 ? 1 : 0) ? 43 : 45);
        
        _image_reset();  
        
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                _texture_draw(((m[y][x] >> 4) & 1) << 2 | (mapdata[y][x] & 3), x, y);
                
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    _texture_draw(7, x, y);
        for (int y = 0; y < IMAGE_HEIGHT; y++)
            for (int x = 0; x < IMAGE_WIDTH; x++) {
                pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
                pixdata[y][x] += 986895 & (rn *= 16777619);
            }
        XPutImage(display, window, 
                  DefaultGC(display, DefaultScreen(display)), 
                  image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
        XMapWindow(display, window);
        XFlush(display);
        
        sleep(1);
    } 
    return 0;
}


Раз уж мы затронули переменную mapdata, обратим внимание на строки и функции, где она изменяется — это функция «b», которую мы пока трогать не будем и «main» где, обратив внимание на содержимое «комплектных» файлов конфигураций проведем рефакторинг:
После рефакторинга по mapdata

#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

/* Код после рефакторинга */

/*! \brief Ширина изображения в пикселях */
#define IMAGE_WIDTH (1220)
/*! \brief Высота изображения в пикселях */
#define IMAGE_HEIGHT (616)
/*! \brief Сдвиг верхней грани карты от левой стороны */
#define IMAGE_SHIFTX (580)

/*! \brief Количество текстур */
#define TEXTURE_COUNT (8)
/*! \brief Ширина текстуры в пикселях */
#define TEXTURE_WIDTH (64)
/*! \brief Высота текстур в пикселях */
#define TEXTURE_HEIGHT (40)
/*! \brief Ширина грани текстуры в пикселях */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief Высота грани текстуры в пикселях */
#define TEXTURE_TOP_HEIGHT (32)

/*! \brief Ширина эмулируемого поля */
#define MAP_WIDTH (19)
/*! \brief Высота эмулируемого поля */
#define MAP_HEIGHT (19)
/*! \brief Количество данные в файле-чертеже. Один байт добавлен для символа '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief Количество итераций во время расчета NOR-узлов */
#define MAP_ITERATIONS (20)

/*! \brief Содержит структуры синтаксиса файла-конфигурации */
enum map_characters {
    MAPCHAR_WIRE  = '.', /**< Провод            (ASCII = 46) */
    MAPCHAR_PLUS  = '+', /**< Провод (есть ток) (ASCII = 43) */
    MAPCHAR_MINUS = '-', /**< Провод (нет тока) (ASCII = 45) */
    MAPCHAR_NOR   = '>', /**< NOR-элемент       (ASCII = 62) */
}

/*! \brief Бинарные данные пикселей изображения.
 * Типизированы к int для оперирования пикселями вместо каналов */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief Текстуры блоков, отображаемых на поле */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief Данные эмулируемого поля. 
 * Один байт добавлен для упрощения обработки символа '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];

/*! \brief Экземпляр дисплея Xlib */
Display * display;
/*! \brief Экземпляр главного окна Xlib */
Window window;
/*! \brief Изображение для вывода на экран */
XImage * image;

/* \brief Обнуляет изображение, заполняя его черным цветом */
static void _image_reset(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++)
            pixdata[y][x] = 0;
}

/*! \brief Отрисовывает текстуру на главном холсте по указанным координатам
 * \param[in] t Индекс текстуры
 * \param[in] x X координата тайла
 * \param[in] y Y координата тайла */
static void _texture_draw(int t, int x, int y) {
    for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
        for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
            if (textures[t][ty][tx])
                pixdata[ty + 
                        y * (TEXTURE_TOP_HEIGHT / 2) + 
                        x * (TEXTURE_TOP_HEIGHT / 2)]
                       [tx + 
                        IMAGE_SHIFTX + 
                        x * (TEXTURE_TOP_WIDTH / 2) - 
                        y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}

/*! \brief Читает данные файла-чертежа и загружает их в карту 
 * \param[in] filename Имя файла-чертежа */
static void _map_read(const char * filename) {
    int f = open(filename, 0);
    read(f, mapdata, MAP_FILEDATA);
    close(f);
}

/*! \brief Заменяет иллюстративные входы из файла-конфигурации на вход
 * в виде провода чтобы работала логика распространения фронта волны */
static void _map_wire_inputs(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            if ((x % 14 == 2) && (y % 4 == 3))
                mapdata[y][x] = MAPCHAR_WIRE;
}

/*! \brief Включает соответствующие входы схемы в зависимости от значения
 * счетчика.
 * \param[in] counter Счетчик */
static void _map_wire_counter(int counter) {
    b(0, 2, 3,  mapdata[3][2],  counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    b(0, 2, 7,  mapdata[7][2],  counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    b(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    b(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/*! \brief Проводит расчет выходного (результирующего) тока после NOR-узла */
static void _map_process_gates(void) {       
    for (int i = 0; i < MAP_ITERATIONS; i++)
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if (mapdata[y][x] == MAPCHAR_NOR)
                    b(0, x + 1, y, mapdata[y][x + 1],
                        !(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
                       || mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ? 
                            MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/* Код до рефакторинга */

int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
int rn = 2166136261;

void *T;

void b(int t, int x, int y, int c, int l) {
    if ((x >= MAP_WIDTH || y >= MAP_HEIGHT || 
         x < 0 || y < 0) || (mapdata[y][x] == l)
        || (mapdata[y][x] != c))
        return;
    mapdata[y][x] = l;
    b(t, x - 1, y, c, l);
    b(t, x + 1, y, c, l);
    b(t, x, y - 1, c, l);
    b(t, x, y + 1, c, l);
}

void e(int t, int x, int y, int c, int l) {
    if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT || 
         x < 0 || y < 0) || 
         (textures[t][y][x] == l) || 
         (textures[t][y][x] != c))
        return;
    textures[t][y][x] = l;
    e(t, x - 1, y, c, l);
    e(t, x + 1, y, c, l);
    e(t, x, y - 1, c, l);
    e(t, x, y + 1, c, l);
}

void k(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x++] = l;
        textures[t][y++][x++] = l;
    }
}

void r(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x--] = l;
        textures[t][y++][x--] = l;
    }
}

void u(int t, int x, int y, int c, int l) {
    while (c--)
        textures[t][y++][x] = l;
}

char *z[8] = { 
    (char[]) {4}, 
    (char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
              21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
              63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
              32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
              21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
              36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
              3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
    (char[]) {5, 1}, 
    (char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
              0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
              21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
              4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
              5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
              63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
              21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
              0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
              3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
              38 - 0,
              4},
    (char[]) {4}, 
    (char[]) {4},
    (char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
              21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
              21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
              16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
              2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
              3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
              3, 30, 38 - 3, 4}, 
    (char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
              0, 8 + 0 + 0, 21, 12 - 0, 1,
              31, 9 + 0, 12 - 0, 1,
              55 - 0 - 0, 21, 12 - 0, 0,
              32, 9 + 3, 12 - 3, 0,
              8 + 3 + 3, 21, 12 - 3, 1,
              31, 9 + 3, 12 - 3, 1,
              55 - 3 - 3, 21, 12 - 3, 6,
              14 + 0, 2, 31 + 0, 13, 4,
              1 - 0, 31 + 0, 16, 7, 3,
              30 + 3 * 0, 14, 6,
              12 + 0 * 4, 3, 32 - 0,
              11 + 0 * 8, 6, 14 + 1, 2,
              31 + 1, 13, 4, 1 - 1,
              31 + 1, 16, 7, 3,
              30 + 3 * 1, 14, 6,
              12 + 1 * 4, 3, 32 - 1,
              11 + 1 * 8,
              4}
};

int main(int a, char *s[]) {
    display = XOpenDisplay(0);
    window = XCreateSimpleWindow(display, 
                                 RootWindow(display, DefaultScreen(display)), 
                                 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
    image = XCreateImage(display, 
                     DefaultVisual(display, DefaultScreen(display)), 
                     DefaultDepth(display, DefaultScreen(display)),
                     2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
    for (int i = 0; i < 8; i++) {
        char *p = z[i];
        int c = 0;
        while (*p != 4) {
            switch (*p) {
            case 0:
                k(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 1:
                r(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 2:
                u(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 3:
                e(i, p[1]
                  , p[2], 0, c);
                p += 3;
                break;
            case 5:
                p = z[p[1]];
                break;
            case 6:
                c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
                p += 2;
                break;
            }
        }
    }
    while (a++) {
        _map_read(s[1]);
        _map_wire_inputs();
        _map_wire_counter(a);
        _map_process_gates();
        
        _image_reset();  
        
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                _texture_draw(((mapdata[y][x] >> 4) & 1) << 2 | (mapdata[y][x] & 3), x, y);
                
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    _texture_draw(7, x, y);
        for (int y = 0; y < IMAGE_HEIGHT; y++)
            for (int x = 0; x < IMAGE_WIDTH; x++) {
                pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
                pixdata[y][x] += 986895 & (rn *= 16777619);
            }
        XPutImage(display, window, 
                  DefaultGC(display, DefaultScreen(display)), 
                  image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
        XMapWindow(display, window);
        XFlush(display);
        
        sleep(1);
    } 
    return 0;
}


Для того, чтобы закончить обработку работы с «mapdata» нужно ответить еще на два вопроса — что такое функция «b»:
void b(int t, int x, int y, int c, int l) {
    if ((x >= MAP_WIDTH || y >= MAP_HEIGHT || 
         x < 0 || y < 0) || (mapdata[y][x] == l)
        || (mapdata[y][x] != c))
        return;
    mapdata[y][x] = l;
    b(t, x - 1, y, c, l);
    b(t, x + 1, y, c, l);
    b(t, x, y - 1, c, l);
    b(t, x, y + 1, c, l);
}

И что происходит в блоке
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                _texture_draw(((mapdata[y][x] >> 4) & 1) << 2 | (mapdata[y][x] & 3), x, y);

Функция «b»


Если внимательно присмотреться к функции «b», то можно заметить, что она до боли похожа на реализацию алгоритма flood_fill, что совпадает с ее теоретическим назначением — она «заливает» «провод» нужным состоянием, позволяя распространять фронт волны тока до конца провода. Переименуем ее и вынесем в блок «production ready».
Flood fill
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

/* Код после рефакторинга */

/*! \brief Ширина изображения в пикселях */
#define IMAGE_WIDTH (1220)
/*! \brief Высота изображения в пикселях */
#define IMAGE_HEIGHT (616)
/*! \brief Сдвиг верхней грани карты от левой стороны */
#define IMAGE_SHIFTX (580)

/*! \brief Количество текстур */
#define TEXTURE_COUNT (8)
/*! \brief Ширина текстуры в пикселях */
#define TEXTURE_WIDTH (64)
/*! \brief Высота текстур в пикселях */
#define TEXTURE_HEIGHT (40)
/*! \brief Ширина грани текстуры в пикселях */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief Высота грани текстуры в пикселях */
#define TEXTURE_TOP_HEIGHT (32)

/*! \brief Ширина эмулируемого поля */
#define MAP_WIDTH (19)
/*! \brief Высота эмулируемого поля */
#define MAP_HEIGHT (19)
/*! \brief Количество данные в файле-чертеже. Один байт добавлен для символа '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief Количество итераций во время расчета NOR-узлов */
#define MAP_ITERATIONS (20)

/*! \brief Содержит структуры синтаксиса файла-конфигурации */
enum map_characters {
    MAPCHAR_WIRE  = '.', /**< Провод            (ASCII = 46) */
    MAPCHAR_PLUS  = '+', /**< Провод (есть ток) (ASCII = 43) */
    MAPCHAR_MINUS = '-', /**< Провод (нет тока) (ASCII = 45) */
    MAPCHAR_NOR   = '>', /**< NOR-элемент       (ASCII = 62) */
};

/*! \brief Бинарные данные пикселей изображения.
 * Типизированы к int для оперирования пикселями вместо каналов */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief Текстуры блоков, отображаемых на поле */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief Данные эмулируемого поля. 
 * Один байт добавлен для упрощения обработки символа '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];

/*! \brief Экземпляр дисплея Xlib */
Display * display;
/*! \brief Экземпляр главного окна Xlib */
Window window;
/*! \brief Изображение для вывода на экран */
XImage * image;

/* \brief Обнуляет изображение, заполняя его черным цветом */
static void _image_reset(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++)
            pixdata[y][x] = 0;
}

/*! \brief Отрисовывает текстуру на главном холсте по указанным координатам
 * \param[in] t Индекс текстуры
 * \param[in] x X координата тайла
 * \param[in] y Y координата тайла */
static void _texture_draw(int t, int x, int y) {
    for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
        for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
            if (textures[t][ty][tx])
                pixdata[ty + 
                        y * (TEXTURE_TOP_HEIGHT / 2) + 
                        x * (TEXTURE_TOP_HEIGHT / 2)]
                       [tx + 
                        IMAGE_SHIFTX + 
                        x * (TEXTURE_TOP_WIDTH / 2) - 
                        y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}

/*! \brief Читает данные файла-чертежа и загружает их в карту 
 * \param[in] filename Имя файла-чертежа */
static void _map_read(const char * filename) {
    int f = open(filename, 0);
    read(f, mapdata, MAP_FILEDATA);
    close(f);
}

/*! \brief Заменяет иллюстративные входы из файла-конфигурации на вход
 * в виде провода чтобы работала логика распространения фронта волны */
static void _map_wire_inputs(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            if ((x % 14 == 2) && (y % 4 == 3))
                mapdata[y][x] = MAPCHAR_WIRE;
}

/*! \brief Производит заливку проводника нужным состоянием
 * \param[in] t Игнорируется, артефакт автогенерации кода 
 * \param[in] x X-координата заливки
 * \param[in] y Y-координата заливки
 * \param[in] c Исходное состояние
 * \param[in] l Целевое состояние */
static void _map_fill(int t, int x, int y, int c, int l) {
    if ((x >= MAP_WIDTH || y >= MAP_HEIGHT || 
         x < 0 || y < 0) || (mapdata[y][x] == l)
        || (mapdata[y][x] != c))
        return;
    mapdata[y][x] = l;
    _map_fill(t, x - 1, y, c, l);
    _map_fill(t, x + 1, y, c, l);
    _map_fill(t, x, y - 1, c, l);
    _map_fill(t, x, y + 1, c, l);
}

/*! \brief Включает соответствующие входы схемы в зависимости от значения
 * счетчика.
 * \param[in] counter Счетчик */
static void _map_wire_counter(int counter) {
    _map_fill(0, 2, 3,  mapdata[3][2],  counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 7,  mapdata[7][2],  counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/*! \brief Проводит расчет выходного (результирующего) тока после NOR-узла */
static void _map_process_gates(void) {       
    for (int i = 0; i < MAP_ITERATIONS; i++)
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if (mapdata[y][x] == MAPCHAR_NOR)
                    _map_fill(0, x + 1, y, mapdata[y][x + 1],
                        !(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
                       || mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ? 
                            MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/* Код до рефакторинга */

int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
int rn = 2166136261;

void *T;

void e(int t, int x, int y, int c, int l) {
    if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT || 
         x < 0 || y < 0) || 
         (textures[t][y][x] == l) || 
         (textures[t][y][x] != c))
        return;
    textures[t][y][x] = l;
    e(t, x - 1, y, c, l);
    e(t, x + 1, y, c, l);
    e(t, x, y - 1, c, l);
    e(t, x, y + 1, c, l);
}

void k(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x++] = l;
        textures[t][y++][x++] = l;
    }
}

void r(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x--] = l;
        textures[t][y++][x--] = l;
    }
}

void u(int t, int x, int y, int c, int l) {
    while (c--)
        textures[t][y++][x] = l;
}

char *z[8] = { 
    (char[]) {4}, 
    (char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
              21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
              63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
              32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
              21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
              36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
              3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
    (char[]) {5, 1}, 
    (char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
              0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
              21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
              4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
              5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
              63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
              21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
              0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
              3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
              38 - 0,
              4},
    (char[]) {4}, 
    (char[]) {4},
    (char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
              21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
              21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
              16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
              2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
              3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
              3, 30, 38 - 3, 4}, 
    (char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
              0, 8 + 0 + 0, 21, 12 - 0, 1,
              31, 9 + 0, 12 - 0, 1,
              55 - 0 - 0, 21, 12 - 0, 0,
              32, 9 + 3, 12 - 3, 0,
              8 + 3 + 3, 21, 12 - 3, 1,
              31, 9 + 3, 12 - 3, 1,
              55 - 3 - 3, 21, 12 - 3, 6,
              14 + 0, 2, 31 + 0, 13, 4,
              1 - 0, 31 + 0, 16, 7, 3,
              30 + 3 * 0, 14, 6,
              12 + 0 * 4, 3, 32 - 0,
              11 + 0 * 8, 6, 14 + 1, 2,
              31 + 1, 13, 4, 1 - 1,
              31 + 1, 16, 7, 3,
              30 + 3 * 1, 14, 6,
              12 + 1 * 4, 3, 32 - 1,
              11 + 1 * 8,
              4}
};

int main(int a, char *s[]) {
    display = XOpenDisplay(0);
    window = XCreateSimpleWindow(display, 
                                 RootWindow(display, DefaultScreen(display)), 
                                 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
    image = XCreateImage(display, 
                     DefaultVisual(display, DefaultScreen(display)), 
                     DefaultDepth(display, DefaultScreen(display)),
                     2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
    for (int i = 0; i < 8; i++) {
        char *p = z[i];
        int c = 0;
        while (*p != 4) {
            switch (*p) {
            case 0:
                k(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 1:
                r(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 2:
                u(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 3:
                e(i, p[1]
                  , p[2], 0, c);
                p += 3;
                break;
            case 5:
                p = z[p[1]];
                break;
            case 6:
                c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
                p += 2;
                break;
            }
        }
    }
    while (a++) {
        _map_read(s[1]);
        _map_wire_inputs();
        _map_wire_counter(a);
        _map_process_gates();
        
        _image_reset();  
        
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                _texture_draw(((mapdata[y][x] >> 4) & 1) << 2 | (mapdata[y][x] & 3), x, y);
                
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    _texture_draw(7, x, y);
        for (int y = 0; y < IMAGE_HEIGHT; y++)
            for (int x = 0; x < IMAGE_WIDTH; x++) {
                pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
                pixdata[y][x] += 986895 & (rn *= 16777619);
            }
        XPutImage(display, window, 
                  DefaultGC(display, DefaultScreen(display)), 
                  image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
        XMapWindow(display, window);
        XFlush(display);
        
        sleep(1);
    } 
    return 0;
}


Странный блок


Теперь осталось разобрать, что происходит в строке
_texture_draw(((mapdata[y][x] >> 4) & 1) << 2 | (mapdata[y][x] & 3), x, y);

Так как мы уже построили полную таблицу состояний, которые могут находиться внутри mapdata то мы можем получить все выходные значения первого параметра:
Ага, то есть по итогам этого преобразования мы получаем индекс текстуры в массиве текстур.
Для того, чтобы продумать механизм генерации из читаемого и ассоциативно понятного набора символов в индексы текстур понадобилась пара часов. Я выписал символы, которые могли означать провода и NOR-элементы а потом расписав их двоичные значения обводил кружочками уникальные области. Кроме текущего был второй вариант с более сложными вычислениями, но он длиннее, следовательно не подошел по лимиту токенов.

Замечательно, это дает нам возможность вычленить еще одну функцию и объявить enum для каждой текстуры:
После очередного рефакторинга:
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

/* Код после рефакторинга */

/*! \brief Ширина изображения в пикселях */
#define IMAGE_WIDTH (1220)
/*! \brief Высота изображения в пикселях */
#define IMAGE_HEIGHT (616)
/*! \brief Сдвиг верхней грани карты от левой стороны */
#define IMAGE_SHIFTX (580)

/*! \brief Количество текстур */
#define TEXTURE_COUNT (8)
/*! \brief Ширина текстуры в пикселях */
#define TEXTURE_WIDTH (64)
/*! \brief Высота текстур в пикселях */
#define TEXTURE_HEIGHT (40)
/*! \brief Ширина грани текстуры в пикселях */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief Высота грани текстуры в пикселях */
#define TEXTURE_TOP_HEIGHT (32)

/*! \brief Ширина эмулируемого поля */
#define MAP_WIDTH (19)
/*! \brief Высота эмулируемого поля */
#define MAP_HEIGHT (19)
/*! \brief Количество данные в файле-чертеже. Один байт добавлен для символа '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief Количество итераций во время расчета NOR-узлов */
#define MAP_ITERATIONS (20)

/*! \brief Содержит структуры синтаксиса файла-конфигурации */
enum map_characters {
    MAPCHAR_WIRE  = '.', /**< Провод            (ASCII = 46) */
    MAPCHAR_PLUS  = '+', /**< Провод (есть ток) (ASCII = 43) */
    MAPCHAR_MINUS = '-', /**< Провод (нет тока) (ASCII = 45) */
    MAPCHAR_NOR   = '>', /**< NOR-элемент       (ASCII = 62) */
    MAPCHAR_EMPTY = ' ', /**< Пустой блок       (ASCII = 32) */
};

/*! \brief Содержит индексы текстур */
enum textures_indexes {
    TEXINDEX_EMPTY = (0), /**< Индекс пустой текстуры                 */
    TEXINDEX_MINUS = (1), /**< Индекс текстуры "выключенного провода" */
    TEXINDEX_WIRE  = (2), /**< Индекс текстуры нейтрального провода   */
    TEXINDEX_PLUS  = (3), /**< Индекс текстуры "включенного" провода  */
    /**/
    TEXINDEX_NOR   = (6)  /**< Индекс текстуры NOR-элемента           */
};

/*! \brief Аргументы программы */
enum program_arguments { 
    ARG_PROGRAM,  /**< Имя самой программы */
    ARG_BLUEPRINT /**< Имя файла-чертежа   */
};

/*! \brief Бинарные данные пикселей изображения.
 * Типизированы к int для оперирования пикселями вместо каналов */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief Текстуры блоков, отображаемых на поле */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief Данные эмулируемого поля. 
 * Один байт добавлен для упрощения обработки символа '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];

/*! \brief Экземпляр дисплея Xlib */
Display * display;
/*! \brief Экземпляр главного окна Xlib */
Window window;
/*! \brief Изображение для вывода на экран */
XImage * image;

/* \brief Обнуляет изображение, заполняя его черным цветом */
static void _image_reset(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++)
            pixdata[y][x] = 0;
}

/*! \brief Конвертирует символ из чертежа в индекс текстуры
 * \param[in] elem Символ чертежа
 * \return Индекс текстуры */
static int _map2texture(char elem) {
    return ((elem >> 4) & 1) << 2 | (elem & 3);
}

/*! \brief Собирает изображение из отдельных тайлов согласно карте */
static void _image_compile(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            _texture_draw(_map2texture(mapdata[y][x]), x, y);
}

/*! \brief Рисует изображение на экране */
static void _image_draw(void) {
    XPutImage(display, window, 
              DefaultGC(display, DefaultScreen(display)), 
              image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
    XMapWindow(display, window);
    XFlush(display);
}

/*! \brief Отрисовывает текстуру на главном холсте по указанным координатам
 * \param[in] t Индекс текстуры
 * \param[in] x X координата тайла
 * \param[in] y Y координата тайла */
static void _texture_draw(int t, int x, int y) {
    for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
        for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
            if (textures[t][ty][tx])
                pixdata[ty + 
                        y * (TEXTURE_TOP_HEIGHT / 2) + 
                        x * (TEXTURE_TOP_HEIGHT / 2)]
                       [tx + 
                        IMAGE_SHIFTX + 
                        x * (TEXTURE_TOP_WIDTH / 2) - 
                        y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}

/*! \brief Читает данные файла-чертежа и загружает их в карту 
 * \param[in] filename Имя файла-чертежа */
static void _map_read(const char * filename) {
    int f = open(filename, 0);
    read(f, mapdata, MAP_FILEDATA);
    close(f);
}

/*! \brief Заменяет иллюстративные входы из файла-конфигурации на вход
 * в виде провода чтобы работала логика распространения фронта волны */
static void _map_wire_inputs(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            if ((x % 14 == 2) && (y % 4 == 3))
                mapdata[y][x] = MAPCHAR_WIRE;
}

/*! \brief Производит заливку проводника нужным состоянием
 * \param[in] t Игнорируется, артефакт автогенерации кода 
 * \param[in] x X-координата заливки
 * \param[in] y Y-координата заливки
 * \param[in] c Исходное состояние
 * \param[in] l Целевое состояние */
static void _map_fill(int t, int x, int y, int c, int l) {
    if ((x >= MAP_WIDTH || y >= MAP_HEIGHT || 
         x < 0 || y < 0) || (mapdata[y][x] == l)
        || (mapdata[y][x] != c))
        return;
    mapdata[y][x] = l;
    _map_fill(t, x - 1, y, c, l);
    _map_fill(t, x + 1, y, c, l);
    _map_fill(t, x, y - 1, c, l);
    _map_fill(t, x, y + 1, c, l);
}

/*! \brief Включает соответствующие входы схемы в зависимости от значения
 * счетчика.
 * \param[in] counter Счетчик */
static void _map_wire_counter(int counter) {
    _map_fill(0, 2, 3,  mapdata[3][2],  counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 7,  mapdata[7][2],  counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/*! \brief Проводит расчет выходного (результирующего) тока после NOR-узла */
static void _map_process_gates(void) {       
    for (int i = 0; i < MAP_ITERATIONS; i++)
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if (mapdata[y][x] == MAPCHAR_NOR)
                    _map_fill(0, x + 1, y, mapdata[y][x + 1],
                        !(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
                       || mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ? 
                            MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/* Код до рефакторинга */

int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
int rn = 2166136261;

void *T;

void e(int t, int x, int y, int c, int l) {
    if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT || 
         x < 0 || y < 0) || 
         (textures[t][y][x] == l) || 
         (textures[t][y][x] != c))
        return;
    textures[t][y][x] = l;
    e(t, x - 1, y, c, l);
    e(t, x + 1, y, c, l);
    e(t, x, y - 1, c, l);
    e(t, x, y + 1, c, l);
}

void k(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x++] = l;
        textures[t][y++][x++] = l;
    }
}

void r(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x--] = l;
        textures[t][y++][x--] = l;
    }
}

void u(int t, int x, int y, int c, int l) {
    while (c--)
        textures[t][y++][x] = l;
}

char *z[8] = { 
    (char[]) {4}, 
    (char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
              21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
              63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
              32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
              21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
              36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
              3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
    (char[]) {5, 1}, 
    (char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
              0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
              21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
              4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
              5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
              63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
              21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
              0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
              3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
              38 - 0,
              4},
    (char[]) {4}, 
    (char[]) {4},
    (char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
              21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
              21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
              16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
              2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
              3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
              3, 30, 38 - 3, 4}, 
    (char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
              0, 8 + 0 + 0, 21, 12 - 0, 1,
              31, 9 + 0, 12 - 0, 1,
              55 - 0 - 0, 21, 12 - 0, 0,
              32, 9 + 3, 12 - 3, 0,
              8 + 3 + 3, 21, 12 - 3, 1,
              31, 9 + 3, 12 - 3, 1,
              55 - 3 - 3, 21, 12 - 3, 6,
              14 + 0, 2, 31 + 0, 13, 4,
              1 - 0, 31 + 0, 16, 7, 3,
              30 + 3 * 0, 14, 6,
              12 + 0 * 4, 3, 32 - 0,
              11 + 0 * 8, 6, 14 + 1, 2,
              31 + 1, 13, 4, 1 - 1,
              31 + 1, 16, 7, 3,
              30 + 3 * 1, 14, 6,
              12 + 1 * 4, 3, 32 - 1,
              11 + 1 * 8,
              4}
};

int main(int argc, char * args[]) {
    display = XOpenDisplay(0);
    window = XCreateSimpleWindow(display, 
                                 RootWindow(display, DefaultScreen(display)), 
                                 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
    image = XCreateImage(display, 
                     DefaultVisual(display, DefaultScreen(display)), 
                     DefaultDepth(display, DefaultScreen(display)),
                     2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
    for (int i = 0; i < 8; i++) {
        char *p = z[i];
        int c = 0;
        while (*p != 4) {
            switch (*p) {
            case 0:
                k(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 1:
                r(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 2:
                u(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 3:
                e(i, p[1]
                  , p[2], 0, c);
                p += 3;
                break;
            case 5:
                p = z[p[1]];
                break;
            case 6:
                c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
                p += 2;
                break;
            }
        }
    }
    unsigned int counter = 0;
    while (counter++) {
        _map_read(args[ARG_BLUEPRINT]);
        _map_wire_inputs();
        _map_wire_counter(counter);
        _map_process_gates();
        
        _image_reset();          
        _image_compile();
        
        
                
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    _texture_draw(7, x, y);
        for (int y = 0; y < IMAGE_HEIGHT; y++)
            for (int x = 0; x < IMAGE_WIDTH; x++) {
                pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
                pixdata[y][x] += 986895 & (rn *= 16777619);
            }
        
        _image_draw();
        
        sleep(1);
    } 
    return 0;
}


Текстура #7


Если присмотреться к массиву «z», то можно заметить, что он содержит 8 блоков данных, как константа количества текстур. И в нем даже есть два пробела на позициях 4 и 5, прямо как в нашем enum, скорее всего это данные текстур. Однако он содержит 8 изображений, а мы смогли «открыть» только 7. Однако, если мы будем достаточно внимательными, то мы сможем заметить, что есть участок кода, который рисует конкретно 7ю текстуру:
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    _texture_draw(7, x, y);

По позиции уже можно догадаться, что это, но закомментируем эти строки и запустим приложение:
До:

После:

Теперь мы точно знаем, что это текстура отверстия на плате и можем добавить ее в список enum, вынеся её отрисовку в отдельную функцию:
Все текстуры в сборе:
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

/* Код после рефакторинга */

/*! \brief Ширина изображения в пикселях */
#define IMAGE_WIDTH (1220)
/*! \brief Высота изображения в пикселях */
#define IMAGE_HEIGHT (616)
/*! \brief Сдвиг верхней грани карты от левой стороны */
#define IMAGE_SHIFTX (580)

/*! \brief Количество текстур */
#define TEXTURE_COUNT (8)
/*! \brief Ширина текстуры в пикселях */
#define TEXTURE_WIDTH (64)
/*! \brief Высота текстур в пикселях */
#define TEXTURE_HEIGHT (40)
/*! \brief Ширина грани текстуры в пикселях */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief Высота грани текстуры в пикселях */
#define TEXTURE_TOP_HEIGHT (32)

/*! \brief Ширина эмулируемого поля */
#define MAP_WIDTH (19)
/*! \brief Высота эмулируемого поля */
#define MAP_HEIGHT (19)
/*! \brief Количество данные в файле-чертеже. Один байт добавлен для символа '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief Количество итераций во время расчета NOR-узлов */
#define MAP_ITERATIONS (20)

/*! \brief Содержит структуры синтаксиса файла-конфигурации */
enum map_characters {
    MAPCHAR_WIRE  = '.', /**< Провод            (ASCII = 46) */
    MAPCHAR_PLUS  = '+', /**< Провод (есть ток) (ASCII = 43) */
    MAPCHAR_MINUS = '-', /**< Провод (нет тока) (ASCII = 45) */
    MAPCHAR_NOR   = '>', /**< NOR-элемент       (ASCII = 62) */
    MAPCHAR_EMPTY = ' ', /**< Пустой блок       (ASCII = 32) */
};

/*! \brief Содержит индексы текстур */
enum textures_indexes {
    TEXINDEX_EMPTY = (0), /**< Индекс пустой текстуры                 */
    TEXINDEX_MINUS = (1), /**< Индекс текстуры "выключенного провода" */
    TEXINDEX_WIRE  = (2), /**< Индекс текстуры нейтрального провода   */
    TEXINDEX_PLUS  = (3), /**< Индекс текстуры "включенного" провода  */
    /**/
    TEXINDEX_NOR   = (6), /**< Индекс текстуры NOR-элемента           */
    TEXINDEX_HOLE  = (7)  /**< Индекс текстуры отверстия на плате     */
};

/*! \brief Аргументы программы */
enum program_arguments { 
    ARG_PROGRAM,  /**< Имя самой программы */
    ARG_BLUEPRINT /**< Имя файла-чертежа   */
};

/*! \brief Бинарные данные пикселей изображения.
 * Типизированы к int для оперирования пикселями вместо каналов */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief Текстуры блоков, отображаемых на поле */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief Данные эмулируемого поля. 
 * Один байт добавлен для упрощения обработки символа '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];

/*! \brief Экземпляр дисплея Xlib */
Display * display;
/*! \brief Экземпляр главного окна Xlib */
Window window;
/*! \brief Изображение для вывода на экран */
XImage * image;

static void _texture_draw(int t, int x, int y);

/*! \brief Создает изображение и сопутствующие сущности */
static void _image_create(void) {
    display = XOpenDisplay(0);
    window = XCreateSimpleWindow(display, 
                                 RootWindow(display, DefaultScreen(display)), 
                                 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
    image = XCreateImage(display, 
                     DefaultVisual(display, DefaultScreen(display)), 
                     DefaultDepth(display, DefaultScreen(display)),
                     2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
}

/* \brief Обнуляет изображение, заполняя его черным цветом */
static void _image_reset(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++)
            pixdata[y][x] = 0;
}

/*! \brief Конвертирует символ из чертежа в индекс текстуры
 * \param[in] elem Символ чертежа
 * \return Индекс текстуры */
static int _map2texture(char elem) {
    return ((elem >> 4) & 1) << 2 | (elem & 3);
}

/*! \brief Собирает изображение из отдельных тайлов согласно карте */
static void _image_compile(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            _texture_draw(_map2texture(mapdata[y][x]), x, y);
}

/*! \brief Рисует изображение на экране */
static void _image_draw(void) {
    XPutImage(display, window, 
              DefaultGC(display, DefaultScreen(display)), 
              image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
    XMapWindow(display, window);
    XFlush(display);
}

/*! \brief Рисует отверстия на печатной плате */
static void _image_drill(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    _texture_draw(TEXINDEX_HOLE, x, y);
}

/*! \brief Отрисовывает текстуру на главном холсте по указанным координатам
 * \param[in] t Индекс текстуры
 * \param[in] x X координата тайла
 * \param[in] y Y координата тайла */
static void _texture_draw(int t, int x, int y) {
    for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
        for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
            if (textures[t][ty][tx])
                pixdata[ty + 
                        y * (TEXTURE_TOP_HEIGHT / 2) + 
                        x * (TEXTURE_TOP_HEIGHT / 2)]
                       [tx + 
                        IMAGE_SHIFTX + 
                        x * (TEXTURE_TOP_WIDTH / 2) - 
                        y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}

/*! \brief Читает данные файла-чертежа и загружает их в карту 
 * \param[in] filename Имя файла-чертежа */
static void _map_read(const char * filename) {
    int f = open(filename, 0);
    read(f, mapdata, MAP_FILEDATA);
    close(f);
}

/*! \brief Заменяет иллюстративные входы из файла-конфигурации на вход
 * в виде провода чтобы работала логика распространения фронта волны */
static void _map_wire_inputs(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            if ((x % 14 == 2) && (y % 4 == 3))
                mapdata[y][x] = MAPCHAR_WIRE;
}

/*! \brief Производит заливку проводника нужным состоянием
 * \param[in] t Игнорируется, артефакт автогенерации кода 
 * \param[in] x X-координата заливки
 * \param[in] y Y-координата заливки
 * \param[in] c Исходное состояние
 * \param[in] l Целевое состояние */
static void _map_fill(int t, int x, int y, int c, int l) {
    if ((x >= MAP_WIDTH || y >= MAP_HEIGHT || 
         x < 0 || y < 0) || (mapdata[y][x] == l)
        || (mapdata[y][x] != c))
        return;
    mapdata[y][x] = l;
    _map_fill(t, x - 1, y, c, l);
    _map_fill(t, x + 1, y, c, l);
    _map_fill(t, x, y - 1, c, l);
    _map_fill(t, x, y + 1, c, l);
}

/*! \brief Включает соответствующие входы схемы в зависимости от значения
 * счетчика.
 * \param[in] counter Счетчик */
static void _map_wire_counter(int counter) {
    _map_fill(0, 2, 3,  mapdata[3][2],  counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 7,  mapdata[7][2],  counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/*! \brief Проводит расчет выходного (результирующего) тока после NOR-узла */
static void _map_process_gates(void) {       
    for (int i = 0; i < MAP_ITERATIONS; i++)
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if (mapdata[y][x] == MAPCHAR_NOR)
                    _map_fill(0, x + 1, y, mapdata[y][x + 1],
                        !(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
                       || mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ? 
                            MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/* Код до рефакторинга */

int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
int rn = 2166136261;

void *T;

void e(int t, int x, int y, int c, int l) {
    if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT || 
         x < 0 || y < 0) || 
         (textures[t][y][x] == l) || 
         (textures[t][y][x] != c))
        return;
    textures[t][y][x] = l;
    e(t, x - 1, y, c, l);
    e(t, x + 1, y, c, l);
    e(t, x, y - 1, c, l);
    e(t, x, y + 1, c, l);
}

void k(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x++] = l;
        textures[t][y++][x++] = l;
    }
}

void r(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x--] = l;
        textures[t][y++][x--] = l;
    }
}

void u(int t, int x, int y, int c, int l) {
    while (c--)
        textures[t][y++][x] = l;
}

char *z[8] = { 
    (char[]) {4}, 
    (char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
              21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
              63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
              32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
              21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
              36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
              3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
    (char[]) {5, 1}, 
    (char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
              0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
              21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
              4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
              5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
              63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
              21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
              0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
              3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
              38 - 0,
              4},
    (char[]) {4}, 
    (char[]) {4},
    (char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
              21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
              21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
              16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
              2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
              3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
              3, 30, 38 - 3, 4}, 
    (char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
              0, 8 + 0 + 0, 21, 12 - 0, 1,
              31, 9 + 0, 12 - 0, 1,
              55 - 0 - 0, 21, 12 - 0, 0,
              32, 9 + 3, 12 - 3, 0,
              8 + 3 + 3, 21, 12 - 3, 1,
              31, 9 + 3, 12 - 3, 1,
              55 - 3 - 3, 21, 12 - 3, 6,
              14 + 0, 2, 31 + 0, 13, 4,
              1 - 0, 31 + 0, 16, 7, 3,
              30 + 3 * 0, 14, 6,
              12 + 0 * 4, 3, 32 - 0,
              11 + 0 * 8, 6, 14 + 1, 2,
              31 + 1, 13, 4, 1 - 1,
              31 + 1, 16, 7, 3,
              30 + 3 * 1, 14, 6,
              12 + 1 * 4, 3, 32 - 1,
              11 + 1 * 8,
              4}
};

int main(int argc, char * args[]) {
    _image_create();

    for (int i = 0; i < 8; i++) {
        char *p = z[i];
        int c = 0;
        while (*p != 4) {
            switch (*p) {
            case 0:
                k(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 1:
                r(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 2:
                u(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 3:
                e(i, p[1]
                  , p[2], 0, c);
                p += 3;
                break;
            case 5:
                p = z[p[1]];
                break;
            case 6:
                c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
                p += 2;
                break;
            }
        }
    }
    unsigned int counter = 1;
    while (counter++) {
        _map_read(args[ARG_BLUEPRINT]);
        _map_wire_inputs();
        _map_wire_counter(counter);
        _map_process_gates();
        
        _image_reset();          
        _image_compile();
        _image_drill();
        
        for (int y = 0; y < IMAGE_HEIGHT; y++)
            for (int x = 0; x < IMAGE_WIDTH; x++) {
                pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
                pixdata[y][x] += 986895 & (rn *= 16777619);
            }
        
        _image_draw();
        
        sleep(1);
    } 
    return 0;
}


Шейдеры


Котики из предыдущей статьи обещали шейдеры. И они тут есть. А где код, который отвечает за их обработку?

        _image_reset();           // Рано
        _image_compile();       // Рано
        _image_drill();            // Рано
        
        for (int y = 0; y < IMAGE_HEIGHT; y++)
            for (int x = 0; x < IMAGE_WIDTH; x++) {
                pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
                pixdata[y][x] += 986895 & (rn *= 16777619);
            }
        
        _image_draw();  // Поздно

Методом исключения понимаем, что зашумленность экрана и эффект LCD-монитора дают эти две строчки. А как они работают?
Начнем с последней:
pixdata[y][x] += 986895 & (rn *= 16777619);

К каждому пикселю прибавляется значение 986895 (что в hex-варианты выглядит как 0x0f0f0f), которое перед этим было посредством операции битовое-И совмещено с результатом умножения rn на 16777619. Если бы rn было ренератором случайных чисел, то это создало бы зернистый «шум» на экране в пределах 16 градаций по каждому каналу. И раз шум появляется, значит rn и есть генератор случайных чисел. Но как это достигается?
int rn = 2166136261;

В самом начале программы переменная rn инициализируется числом 2166136261. А на каждой итерации пикселя умножается на 16777619. Это ничто иное, как генератор псевдослучайных чисел. Вот только вместо линейного хорошо изученного генератора используется алгоритм хэширования FNV без шага с XOR, поскольку нам не нужен конечный результат.

Остается понять, как работает предыдущая строка:

pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));

Переведем число 14737632 в шестнадцатиричный формат, так как мы работаем с однобайтными каналами света: 0xe0e0e0. А теперь приняв x равным от 0 до 3 проведем соответствующие вычисления:

0xe0e0e0 | (31 << ((0 % 3) << 3)) = e0e0ff                                                                                                                                                                  
0xe0e0e0 | (31 << ((1 % 3) << 3)) = e0ffe0                                                                                                                                                                        
0xe0e0e0 | (31 << ((2 % 3) << 3)) = ffe0e0 

Если теперь эти маски применить при помощи операции "&" к цвету пикселя, то мы получим, соответственно, приглушенные R и G, R и B, G и B каналы, что будет выглядеть как эффект от LCD-монитора:
Выделим их в отдельные функции:
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

/* Код после рефакторинга */

/*! \brief Ширина изображения в пикселях */
#define IMAGE_WIDTH (1220)
/*! \brief Высота изображения в пикселях */
#define IMAGE_HEIGHT (616)
/*! \brief Сдвиг верхней грани карты от левой стороны */
#define IMAGE_SHIFTX (580)

/*! \brief Количество текстур */
#define TEXTURE_COUNT (8)
/*! \brief Ширина текстуры в пикселях */
#define TEXTURE_WIDTH (64)
/*! \brief Высота текстур в пикселях */
#define TEXTURE_HEIGHT (40)
/*! \brief Ширина грани текстуры в пикселях */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief Высота грани текстуры в пикселях */
#define TEXTURE_TOP_HEIGHT (32)

/*! \brief Ширина эмулируемого поля */
#define MAP_WIDTH (19)
/*! \brief Высота эмулируемого поля */
#define MAP_HEIGHT (19)
/*! \brief Количество данные в файле-чертеже. Один байт добавлен для символа '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief Количество итераций во время расчета NOR-узлов */
#define MAP_ITERATIONS (20)

/*! \brief Содержит структуры синтаксиса файла-конфигурации */
enum map_characters {
    MAPCHAR_WIRE  = '.', /**< Провод            (ASCII = 46) */
    MAPCHAR_PLUS  = '+', /**< Провод (есть ток) (ASCII = 43) */
    MAPCHAR_MINUS = '-', /**< Провод (нет тока) (ASCII = 45) */
    MAPCHAR_NOR   = '>', /**< NOR-элемент       (ASCII = 62) */
    MAPCHAR_EMPTY = ' ', /**< Пустой блок       (ASCII = 32) */
};

/*! \brief Содержит индексы текстур */
enum textures_indexes {
    TEXINDEX_EMPTY = (0), /**< Индекс пустой текстуры                 */
    TEXINDEX_MINUS = (1), /**< Индекс текстуры "выключенного провода" */
    TEXINDEX_WIRE  = (2), /**< Индекс текстуры нейтрального провода   */
    TEXINDEX_PLUS  = (3), /**< Индекс текстуры "включенного" провода  */
    /**/
    TEXINDEX_NOR   = (6), /**< Индекс текстуры NOR-элемента           */
    TEXINDEX_HOLE  = (7)  /**< Индекс текстуры отверстия на плате     */
};

/*! \brief Аргументы программы */
enum program_arguments { 
    ARG_PROGRAM,  /**< Имя самой программы */
    ARG_BLUEPRINT /**< Имя файла-чертежа   */
};

/*! \brief Бинарные данные пикселей изображения.
 * Типизированы к int для оперирования пикселями вместо каналов */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief Текстуры блоков, отображаемых на поле */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief Данные эмулируемого поля. 
 * Один байт добавлен для упрощения обработки символа '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];
/*! \brief Зерно генератора случайных чисел */
int random = 2166136261;

/*! \brief Экземпляр дисплея Xlib */
Display * display;
/*! \brief Экземпляр главного окна Xlib */
Window window;
/*! \brief Изображение для вывода на экран */
XImage * image;

static void _texture_draw(int t, int x, int y);

/*! \brief Создает изображение и сопутствующие сущности */
static void _image_create(void) {
    display = XOpenDisplay(0);
    window = XCreateSimpleWindow(display, 
                                 RootWindow(display, DefaultScreen(display)), 
                                 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
    image = XCreateImage(display, 
                     DefaultVisual(display, DefaultScreen(display)), 
                     DefaultDepth(display, DefaultScreen(display)),
                     2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
}

/* \brief Обнуляет изображение, заполняя его черным цветом */
static void _image_reset(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++)
            pixdata[y][x] = 0;
}

/*! \brief Конвертирует символ из чертежа в индекс текстуры
 * \param[in] elem Символ чертежа
 * \return Индекс текстуры */
static int _map2texture(char elem) {
    return ((elem >> 4) & 1) << 2 | (elem & 3);
}

/*! \brief Собирает изображение из отдельных тайлов согласно карте */
static void _image_compile(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            _texture_draw(_map2texture(mapdata[y][x]), x, y);
}

/*! \brief Рисует изображение на экране */
static void _image_draw(void) {
    XPutImage(display, window, 
              DefaultGC(display, DefaultScreen(display)), 
              image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
    XMapWindow(display, window);
    XFlush(display);
}

/*! \brief Рисует отверстия на печатной плате */
static void _image_drill(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    _texture_draw(TEXINDEX_HOLE, x, y);
}

/*! \brief Применяет шейдер LCD-эффекта на изображение
 * \param[in] x X-координата изображения
 * \param[in] y Y-координата изображения */
static void _shader_lcd(int x, int y) {
    pixdata[y][x] &= 0xe0e0e0 | (31 << ((x % 3) << 3));
}

/*! \brief Применяет шейдер случайного шума на изображение
 * \param[in] x X-координата изображения
 * \param[in] y Y-координата изображения */
static void _shader_noise(int x, int y) {
    pixdata[y][x] += 0x0f0f0f & (random *= 16777619);
}

/*! \brief Накладывает на изображение различные эффекты */
static void _image_postprocess(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++) {
            _shader_lcd(x, y);
            _shader_noise(x, y);
        }
}

/*! \brief Отрисовывает текстуру на главном холсте по указанным координатам
 * \param[in] t Индекс текстуры
 * \param[in] x X координата тайла
 * \param[in] y Y координата тайла */
static void _texture_draw(int t, int x, int y) {
    for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
        for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
            if (textures[t][ty][tx])
                pixdata[ty + 
                        y * (TEXTURE_TOP_HEIGHT / 2) + 
                        x * (TEXTURE_TOP_HEIGHT / 2)]
                       [tx + 
                        IMAGE_SHIFTX + 
                        x * (TEXTURE_TOP_WIDTH / 2) - 
                        y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}

/*! \brief Читает данные файла-чертежа и загружает их в карту 
 * \param[in] filename Имя файла-чертежа */
static void _map_read(const char * filename) {
    int f = open(filename, 0);
    read(f, mapdata, MAP_FILEDATA);
    close(f);
}

/*! \brief Заменяет иллюстративные входы из файла-конфигурации на вход
 * в виде провода чтобы работала логика распространения фронта волны */
static void _map_wire_inputs(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            if ((x % 14 == 2) && (y % 4 == 3))
                mapdata[y][x] = MAPCHAR_WIRE;
}

/*! \brief Производит заливку проводника нужным состоянием
 * \param[in] t Игнорируется, артефакт автогенерации кода 
 * \param[in] x X-координата заливки
 * \param[in] y Y-координата заливки
 * \param[in] c Исходное состояние
 * \param[in] l Целевое состояние */
static void _map_fill(int t, int x, int y, int c, int l) {
    if ((x >= MAP_WIDTH || y >= MAP_HEIGHT || 
         x < 0 || y < 0) || (mapdata[y][x] == l)
        || (mapdata[y][x] != c))
        return;
    mapdata[y][x] = l;
    _map_fill(t, x - 1, y, c, l);
    _map_fill(t, x + 1, y, c, l);
    _map_fill(t, x, y - 1, c, l);
    _map_fill(t, x, y + 1, c, l);
}

/*! \brief Включает соответствующие входы схемы в зависимости от значения
 * счетчика.
 * \param[in] counter Счетчик */
static void _map_wire_counter(int counter) {
    _map_fill(0, 2, 3,  mapdata[3][2],  counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 7,  mapdata[7][2],  counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/*! \brief Проводит расчет выходного (результирующего) тока после NOR-узла */
static void _map_process_gates(void) {       
    for (int i = 0; i < MAP_ITERATIONS; i++)
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if (mapdata[y][x] == MAPCHAR_NOR)
                    _map_fill(0, x + 1, y, mapdata[y][x + 1],
                        !(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
                       || mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ? 
                            MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/* Код до рефакторинга */

int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };

void e(int t, int x, int y, int c, int l) {
    if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT || 
         x < 0 || y < 0) || 
         (textures[t][y][x] == l) || 
         (textures[t][y][x] != c))
        return;
    textures[t][y][x] = l;
    e(t, x - 1, y, c, l);
    e(t, x + 1, y, c, l);
    e(t, x, y - 1, c, l);
    e(t, x, y + 1, c, l);
}

void k(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x++] = l;
        textures[t][y++][x++] = l;
    }
}

void r(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x--] = l;
        textures[t][y++][x--] = l;
    }
}

void u(int t, int x, int y, int c, int l) {
    while (c--)
        textures[t][y++][x] = l;
}

char *z[8] = { 
    (char[]) {4}, 
    (char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
              21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
              63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
              32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
              21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
              36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
              3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
    (char[]) {5, 1}, 
    (char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
              0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
              21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
              4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
              5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
              63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
              21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
              0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
              3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
              38 - 0,
              4},
    (char[]) {4}, 
    (char[]) {4},
    (char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
              21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
              21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
              16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
              2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
              3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
              3, 30, 38 - 3, 4}, 
    (char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
              0, 8 + 0 + 0, 21, 12 - 0, 1,
              31, 9 + 0, 12 - 0, 1,
              55 - 0 - 0, 21, 12 - 0, 0,
              32, 9 + 3, 12 - 3, 0,
              8 + 3 + 3, 21, 12 - 3, 1,
              31, 9 + 3, 12 - 3, 1,
              55 - 3 - 3, 21, 12 - 3, 6,
              14 + 0, 2, 31 + 0, 13, 4,
              1 - 0, 31 + 0, 16, 7, 3,
              30 + 3 * 0, 14, 6,
              12 + 0 * 4, 3, 32 - 0,
              11 + 0 * 8, 6, 14 + 1, 2,
              31 + 1, 13, 4, 1 - 1,
              31 + 1, 16, 7, 3,
              30 + 3 * 1, 14, 6,
              12 + 1 * 4, 3, 32 - 1,
              11 + 1 * 8,
              4}
};

int main(int argc, char * args[]) {
    _image_create();

    for (int i = 0; i < 8; i++) {
        char *p = z[i];
        int c = 0;
        while (*p != 4) {
            switch (*p) {
            case 0:
                k(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 1:
                r(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 2:
                u(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 3:
                e(i, p[1]
                  , p[2], 0, c);
                p += 3;
                break;
            case 5:
                p = z[p[1]];
                break;
            case 6:
                c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
                p += 2;
                break;
            }
        }
    }
    unsigned int counter = 1;
    while (counter++) {
        _map_read(args[ARG_BLUEPRINT]);
        _map_wire_inputs();
        _map_wire_counter(counter);
        _map_process_gates();
        
        _image_reset();          
        _image_compile();
        _image_drill();
        _image_postprocess();        
        _image_draw();
        
        sleep(1);
    } 
    return 0;
}


«e», «k», «r», «u»


Осталось еще 4 функции, которые мы не исследовали и не переименовали — это «e», «k», «r» и «u». Попытаемся осмотреть их, не прибегая к поиску мест, откуда они вызываются:
void e(int t, int x, int y, int c, int l) {
    if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT || 
         x < 0 || y < 0) || 
         (textures[t][y][x] == l) || 
         (textures[t][y][x] != c))
        return;
    textures[t][y][x] = l;
    e(t, x - 1, y, c, l);
    e(t, x + 1, y, c, l);
    e(t, x, y - 1, c, l);
    e(t, x, y + 1, c, l);
}

Очевидно, что эта функция выглядит и работает как flood_fill, только для массива textures, переименуем ее в _texture_fill.
void k(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x++] = l;
        textures[t][y++][x++] = l;
    }
}

void r(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x--] = l;
        textures[t][y++][x--] = l;
    }
}

Функции «k» и «r» на каждую заданную единицу c рисуют два пикселя значением l и перемещаются вправо или влево на два пикселя и вниз на один — значит это функции рисования изометрических линий SW и SE. Переименуем их в _texture_linesw и _texture_linese.

На данный момент уже можно догадаться, что последняя функция «u» рисует линию вертикально вниз:

void u(int t, int x, int y, int c, int l) {
    while (c--)
        textures[t][y++][x] = l;
}

Переименуем её в _texture_linedown.
Все отдельные функции прошли рефакторинг:
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

/* Код после рефакторинга */

/*! \brief Ширина изображения в пикселях */
#define IMAGE_WIDTH (1220)
/*! \brief Высота изображения в пикселях */
#define IMAGE_HEIGHT (616)
/*! \brief Сдвиг верхней грани карты от левой стороны */
#define IMAGE_SHIFTX (580)

/*! \brief Количество текстур */
#define TEXTURE_COUNT (8)
/*! \brief Ширина текстуры в пикселях */
#define TEXTURE_WIDTH (64)
/*! \brief Высота текстур в пикселях */
#define TEXTURE_HEIGHT (40)
/*! \brief Ширина грани текстуры в пикселях */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief Высота грани текстуры в пикселях */
#define TEXTURE_TOP_HEIGHT (32)

/*! \brief Ширина эмулируемого поля */
#define MAP_WIDTH (19)
/*! \brief Высота эмулируемого поля */
#define MAP_HEIGHT (19)
/*! \brief Количество данные в файле-чертеже. Один байт добавлен для символа '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief Количество итераций во время расчета NOR-узлов */
#define MAP_ITERATIONS (20)

/*! \brief Содержит структуры синтаксиса файла-конфигурации */
enum map_characters {
    MAPCHAR_WIRE  = '.', /**< Провод            (ASCII = 46) */
    MAPCHAR_PLUS  = '+', /**< Провод (есть ток) (ASCII = 43) */
    MAPCHAR_MINUS = '-', /**< Провод (нет тока) (ASCII = 45) */
    MAPCHAR_NOR   = '>', /**< NOR-элемент       (ASCII = 62) */
    MAPCHAR_EMPTY = ' ', /**< Пустой блок       (ASCII = 32) */
};

/*! \brief Содержит индексы текстур */
enum textures_indexes {
    TEXINDEX_EMPTY = (0), /**< Индекс пустой текстуры                 */
    TEXINDEX_MINUS = (1), /**< Индекс текстуры "выключенного провода" */
    TEXINDEX_WIRE  = (2), /**< Индекс текстуры нейтрального провода   */
    TEXINDEX_PLUS  = (3), /**< Индекс текстуры "включенного" провода  */
    /**/
    TEXINDEX_NOR   = (6), /**< Индекс текстуры NOR-элемента           */
    TEXINDEX_HOLE  = (7)  /**< Индекс текстуры отверстия на плате     */
};

/*! \brief Аргументы программы */
enum program_arguments { 
    ARG_PROGRAM,  /**< Имя самой программы */
    ARG_BLUEPRINT /**< Имя файла-чертежа   */
};

/*! \brief Бинарные данные пикселей изображения.
 * Типизированы к int для оперирования пикселями вместо каналов */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief Текстуры блоков, отображаемых на поле */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief Данные эмулируемого поля. 
 * Один байт добавлен для упрощения обработки символа '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];
/*! \brief Зерно генератора случайных чисел */
int random = 2166136261;

/*! \brief Экземпляр дисплея Xlib */
Display * display;
/*! \brief Экземпляр главного окна Xlib */
Window window;
/*! \brief Изображение для вывода на экран */
XImage * image;

static void _texture_draw(int t, int x, int y);

/*! \brief Создает изображение и сопутствующие сущности */
static void _image_create(void) {
    display = XOpenDisplay(0);
    window = XCreateSimpleWindow(display, 
                                 RootWindow(display, DefaultScreen(display)), 
                                 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
    image = XCreateImage(display, 
                     DefaultVisual(display, DefaultScreen(display)), 
                     DefaultDepth(display, DefaultScreen(display)),
                     2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
}

/* \brief Обнуляет изображение, заполняя его черным цветом */
static void _image_reset(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++)
            pixdata[y][x] = 0;
}

/*! \brief Конвертирует символ из чертежа в индекс текстуры
 * \param[in] elem Символ чертежа
 * \return Индекс текстуры */
static int _map2texture(char elem) {
    return ((elem >> 4) & 1) << 2 | (elem & 3);
}

/*! \brief Собирает изображение из отдельных тайлов согласно карте */
static void _image_compile(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            _texture_draw(_map2texture(mapdata[y][x]), x, y);
}

/*! \brief Рисует изображение на экране */
static void _image_draw(void) {
    XPutImage(display, window, 
              DefaultGC(display, DefaultScreen(display)), 
              image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
    XMapWindow(display, window);
    XFlush(display);
}

/*! \brief Рисует отверстия на печатной плате */
static void _image_drill(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    _texture_draw(TEXINDEX_HOLE, x, y);
}

/*! \brief Применяет шейдер LCD-эффекта на изображение
 * \param[in] x X-координата изображения
 * \param[in] y Y-координата изображения */
static void _shader_lcd(int x, int y) {
    pixdata[y][x] &= 0xe0e0e0 | (31 << ((x % 3) << 3));
}

/*! \brief Применяет шейдер случайного шума на изображение
 * \param[in] x X-координата изображения
 * \param[in] y Y-координата изображения */
static void _shader_noise(int x, int y) {
    pixdata[y][x] += 0x0f0f0f & (random *= 16777619);
}

/*! \brief Накладывает на изображение различные эффекты */
static void _image_postprocess(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++) {
            _shader_lcd(x, y);
            _shader_noise(x, y);
        }
}

/*! \brief Отрисовывает текстуру на главном холсте по указанным координатам
 * \param[in] t Индекс текстуры
 * \param[in] x X координата тайла
 * \param[in] y Y координата тайла */
static void _texture_draw(int t, int x, int y) {
    for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
        for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
            if (textures[t][ty][tx])
                pixdata[ty + 
                        y * (TEXTURE_TOP_HEIGHT / 2) + 
                        x * (TEXTURE_TOP_HEIGHT / 2)]
                       [tx + 
                        IMAGE_SHIFTX + 
                        x * (TEXTURE_TOP_WIDTH / 2) - 
                        y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}

/*! \brief Производит закраску области текстуры
 * \param[in] t Индекс текстуры
 * \param[in] x X-координата начала
 * \param[in] y Y-координата начала
 * \param[in] source Исходный цвет
 * \param[in] target Новый цвет */
static void _texture_fill(int t, int x, int y, int source, int target) {
    if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT || 
         x < 0 || y < 0) || 
         (textures[t][y][x] == target) || 
         (textures[t][y][x] != source))
        return;
    textures[t][y][x] = target;
    _texture_fill(t, x - 1, y, source, target);
    _texture_fill(t, x + 1, y, source, target);
    _texture_fill(t, x, y - 1, source, target);
    _texture_fill(t, x, y + 1, source, target);
}

/*! \brief Рисует изометрическую линию по направлению SE
 * \param[in] t Индекс текстуры
 * \param[in] x X-координата начала
 * \param[in] y Y-координата начала
 * \param[in] c Длина линии по короткой стороне
 * \param[in] color Цвет рисования */
static void _texture_linese(int t, int x, int y, int c, int color) {
    while (c--) {
        textures[t][y][x++] = color;
        textures[t][y++][x++] = color;
    }
}

/*! \brief Рисует изометрическую линию по направлению SW
 * \param[in] t Индекс текстуры
 * \param[in] x X-координата начала
 * \param[in] y Y-координата начала
 * \param[in] c Длина линии по короткой стороне
 * \param[in] color Цвет рисования */
static void _texture_linesw(int t, int x, int y, int c, int color) {
    while (c--) {
        textures[t][y][x--] = color;
        textures[t][y++][x--] = color;
    }
}

/*! \brief Рисует линию вниз
 * \param[in] t Индекс текстуры
 * \param[in] x X-координата начала
 * \param[in] y Y-координата начала
 * \param[in] c Длина линии
 * \param[in] color Цвет рисования */
static void _texture_linedown(int t, int x, int y, int c, int color) {
    while (c--)
        textures[t][y++][x] = color;
}

/*! \brief Читает данные файла-чертежа и загружает их в карту 
 * \param[in] filename Имя файла-чертежа */
static void _map_read(const char * filename) {
    int f = open(filename, 0);
    read(f, mapdata, MAP_FILEDATA);
    close(f);
}

/*! \brief Заменяет иллюстративные входы из файла-конфигурации на вход
 * в виде провода чтобы работала логика распространения фронта волны */
static void _map_wire_inputs(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            if ((x % 14 == 2) && (y % 4 == 3))
                mapdata[y][x] = MAPCHAR_WIRE;
}

/*! \brief Производит заливку проводника нужным состоянием
 * \param[in] t Игнорируется, артефакт автогенерации кода 
 * \param[in] x X-координата заливки
 * \param[in] y Y-координата заливки
 * \param[in] c Исходное состояние
 * \param[in] l Целевое состояние */
static void _map_fill(int t, int x, int y, int c, int l) {
    if ((x >= MAP_WIDTH || y >= MAP_HEIGHT || 
         x < 0 || y < 0) || (mapdata[y][x] == l)
        || (mapdata[y][x] != c))
        return;
    mapdata[y][x] = l;
    _map_fill(t, x - 1, y, c, l);
    _map_fill(t, x + 1, y, c, l);
    _map_fill(t, x, y - 1, c, l);
    _map_fill(t, x, y + 1, c, l);
}

/*! \brief Включает соответствующие входы схемы в зависимости от значения
 * счетчика.
 * \param[in] counter Счетчик */
static void _map_wire_counter(int counter) {
    _map_fill(0, 2, 3,  mapdata[3][2],  counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 7,  mapdata[7][2],  counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/*! \brief Проводит расчет выходного (результирующего) тока после NOR-узла */
static void _map_process_gates(void) {       
    for (int i = 0; i < MAP_ITERATIONS; i++)
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if (mapdata[y][x] == MAPCHAR_NOR)
                    _map_fill(0, x + 1, y, mapdata[y][x + 1],
                        !(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
                       || mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ? 
                            MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/* Код до рефакторинга */

int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };

char *z[8] = { 
    (char[]) {4}, 
    (char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
              21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
              63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
              32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
              21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
              36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
              3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
    (char[]) {5, 1}, 
    (char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
              0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
              21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
              4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
              5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
              63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
              21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
              0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
              3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
              38 - 0,
              4},
    (char[]) {4}, 
    (char[]) {4},
    (char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
              21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
              21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
              16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
              2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
              3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
              3, 30, 38 - 3, 4}, 
    (char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
              0, 8 + 0 + 0, 21, 12 - 0, 1,
              31, 9 + 0, 12 - 0, 1,
              55 - 0 - 0, 21, 12 - 0, 0,
              32, 9 + 3, 12 - 3, 0,
              8 + 3 + 3, 21, 12 - 3, 1,
              31, 9 + 3, 12 - 3, 1,
              55 - 3 - 3, 21, 12 - 3, 6,
              14 + 0, 2, 31 + 0, 13, 4,
              1 - 0, 31 + 0, 16, 7, 3,
              30 + 3 * 0, 14, 6,
              12 + 0 * 4, 3, 32 - 0,
              11 + 0 * 8, 6, 14 + 1, 2,
              31 + 1, 13, 4, 1 - 1,
              31 + 1, 16, 7, 3,
              30 + 3 * 1, 14, 6,
              12 + 1 * 4, 3, 32 - 1,
              11 + 1 * 8,
              4}
};

int main(int argc, char * args[]) {
    _image_create();

    for (int i = 0; i < 8; i++) {
        char *p = z[i];
        int c = 0;
        while (*p != 4) {
            switch (*p) {
            case 0:
                _texture_linese(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 1:
                _texture_linesw(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 2:
                _texture_linedown(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 3:
                _texture_fill(i, p[1], p[2], 0, c);
                p += 3;
                break;
            case 5:
                p = z[p[1]];
                break;
            case 6:
                c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
                p += 2;
                break;
            }
        }
    }
    unsigned int counter = 1;
    while (counter++) {
        _map_read(args[ARG_BLUEPRINT]);
        _map_wire_inputs();
        _map_wire_counter(counter);
        _map_process_gates();
        
        _image_reset();          
        _image_compile();
        _image_drill();
        _image_postprocess();        
        _image_draw();
        
        sleep(1);
    } 
    return 0;
}


Векторная графика


Остался последний шаг — до конца разобраться, что же происходит в последнем, оставленном «на потом», switch-case:
    for (int i = 0; i < 8; i++) {
        char *p = z[i];
        int c = 0;
        while (*p != 4) {
            switch (*p) {
            case 0:
                _texture_linese(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 1:
                _texture_linesw(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 2:
                _texture_linedown(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 3:
                _texture_fill(i, p[1], p[2], 0, c);
                p += 3;
                break;
            case 5:
                p = z[p[1]];
                break;
            case 6:
                c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
                p += 2;
                break;
            }
        }
    }

Теперь, когда функции имеют новые, понятные, имена, можно сказать, что этот блок кода интерпретирует данные из массива «z», и согласно инструкциям, содержащимся в нем (например 0, 5, 5, 8, 2 — «нарисовать линию South-East, от [5,5] длиной 8 пикселей по краткой стороне цветом номер 2») рисует весь набор текстур.
Вроде бы всё понятно, но ни одного указания на цвет в программе замечено не было.
c = _x[p[1] / 4] - 1643277 * (p[1] % 4);

Ага, значит массив _x — это палитра, но в очень странном, «сжатом», формате.
int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };

Так как мы пока не знаем, сколько всего цветов используется в палитре (при установке цвета индекс как минимум делится на 4), переформатируем таблицу данных для отрисовки и группируем числа по категориям, заменив сигнатуры инструкций на константы:
Рефакторинг таблицы векторных инструкций
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

/* Код после рефакторинга */

/*! \brief Ширина изображения в пикселях */
#define IMAGE_WIDTH (1220)
/*! \brief Высота изображения в пикселях */
#define IMAGE_HEIGHT (616)
/*! \brief Сдвиг верхней грани карты от левой стороны */
#define IMAGE_SHIFTX (580)

/*! \brief Количество текстур */
#define TEXTURE_COUNT (8)
/*! \brief Ширина текстуры в пикселях */
#define TEXTURE_WIDTH (64)
/*! \brief Высота текстур в пикселях */
#define TEXTURE_HEIGHT (40)
/*! \brief Ширина грани текстуры в пикселях */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief Высота грани текстуры в пикселях */
#define TEXTURE_TOP_HEIGHT (32)

/*! \brief Ширина эмулируемого поля */
#define MAP_WIDTH (19)
/*! \brief Высота эмулируемого поля */
#define MAP_HEIGHT (19)
/*! \brief Количество данные в файле-чертеже. Один байт добавлен для символа '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief Количество итераций во время расчета NOR-узлов */
#define MAP_ITERATIONS (20)

/*! \brief Содержит структуры синтаксиса файла-конфигурации */
enum map_characters {
    MAPCHAR_WIRE  = '.', /**< Провод            (ASCII = 46) */
    MAPCHAR_PLUS  = '+', /**< Провод (есть ток) (ASCII = 43) */
    MAPCHAR_MINUS = '-', /**< Провод (нет тока) (ASCII = 45) */
    MAPCHAR_NOR   = '>', /**< NOR-элемент       (ASCII = 62) */
    MAPCHAR_EMPTY = ' ', /**< Пустой блок       (ASCII = 32) */
};

/*! \brief Содержит индексы текстур */
enum textures_indexes {
    TEXINDEX_EMPTY = (0), /**< Индекс пустой текстуры                 */
    TEXINDEX_MINUS = (1), /**< Индекс текстуры "выключенного провода" */
    TEXINDEX_WIRE  = (2), /**< Индекс текстуры нейтрального провода   */
    TEXINDEX_PLUS  = (3), /**< Индекс текстуры "включенного" провода  */
    /**/
    TEXINDEX_NOR   = (6), /**< Индекс текстуры NOR-элемента           */
    TEXINDEX_HOLE  = (7)  /**< Индекс текстуры отверстия на плате     */
};

/*! \brief Список инструкций векторного интерпретатора */
enum textures_instructions {
    TEXVEC_LINESE = (0), /**< Линия SE                          */
    TEXVEC_LINESW = (1), /**< Линия SW                          */
    TEXVEC_LINEDW = (2), /**< Линия вниз                        */
    TEXVEC_FILL   = (3), /**< Заливка                           */
    TEXVEC_EXIT   = (4), /**< Конец списка инструкций           */
    TEXVEC_REPEAT = (5), /**< Повтор инструкций другой текстуры */
    TEXVEC_COLOR  = (6)  /**< Выбор цвета                       */
};

/*! \brief Аргументы программы */
enum program_arguments { 
    ARG_PROGRAM,  /**< Имя самой программы */
    ARG_BLUEPRINT /**< Имя файла-чертежа   */
};

/*! \brief Бинарные данные пикселей изображения.
 * Типизированы к int для оперирования пикселями вместо каналов */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief Текстуры блоков, отображаемых на поле */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief Данные эмулируемого поля. 
 * Один байт добавлен для упрощения обработки символа '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];
/*! \brief Зерно генератора случайных чисел */
int random = 2166136261;

/*! \brief Экземпляр дисплея Xlib */
Display * display;
/*! \brief Экземпляр главного окна Xlib */
Window window;
/*! \brief Изображение для вывода на экран */
XImage * image;

/*! \brief Векторные инструкции для рисования текстур */
static const char * vecdata[TEXTURE_COUNT] = { 
    /* TEXINDEX_EMPTY */
    (char[]) { TEXVEC_EXIT }, 
    /* TEXINDEX_MINUS */
    (char[]) { TEXVEC_COLOR,   5,            TEXVEC_LINESE, 32,  5, 16, 
               TEXVEC_LINESE,  0, 21, 16,    TEXVEC_LINESW, 63, 21, 16, 
               TEXVEC_LINEDW,  0, 21,  4,    TEXVEC_LINEDW, 31, 36,  4, 
               TEXVEC_LINESW, 31,  5, 16,    TEXVEC_LINESE,  0, 24, 16, 
               TEXVEC_LINESW, 63, 24, 16,    TEXVEC_LINEDW, 63, 21,  4, 
               TEXVEC_LINEDW, 32, 36,  4,    TEXVEC_COLOR,   4, 
               TEXVEC_FILL,   31, 8,         TEXVEC_COLOR,   6,
               TEXVEC_FILL,   33, 38,        TEXVEC_COLOR,   7, 
               TEXVEC_FILL,   30, 38,        TEXVEC_EXIT },
    /* TEXINDEX_WIRE */
    (char[]) { TEXVEC_REPEAT,  1 }, 
    /* TEXINDEX_PLUS */
    (char[]) { TEXVEC_COLOR,   1,            TEXVEC_LINESE, 32,  5, 16,
               TEXVEC_LINESE,  0, 21, 16,    TEXVEC_LINESW, 63, 21, 16, 
               TEXVEC_LINEDW, 63, 21,  4,    TEXVEC_LINEDW, 31, 36,  4, 
               TEXVEC_LINESW, 31,  5, 16,    TEXVEC_LINESE,  0, 24, 16, 
               TEXVEC_LINESW, 63, 24, 16,    TEXVEC_LINEDW, 63, 21,  4, 
               TEXVEC_LINEDW, 32, 36,  4,    TEXVEC_COLOR,   0, 
               TEXVEC_FILL,   31,  8,        TEXVEC_COLOR,   2,
               TEXVEC_FILL,   33, 38,        TEXVEC_COLOR,   3, 
               TEXVEC_FILL,   30, 38,        TEXVEC_EXIT },
    /* Не используется */
    (char[]) { TEXVEC_EXIT }, 
    /* Не используется */
    (char[]) { TEXVEC_EXIT },
    /* TEXINDEX_NOR */
    (char[]) { TEXVEC_COLOR,   9,            TEXVEC_LINESE, 32,  2, 16, 
               TEXVEC_LINESE,  0, 18, 16,    TEXVEC_LINESW, 63, 18, 16, 
               TEXVEC_LINEDW,  0, 18,  4,    TEXVEC_LINEDW, 31, 33,  4, 
               TEXVEC_LINESW, 31,  2, 16,    TEXVEC_LINESE,  0, 21, 16, 
               TEXVEC_LINESW, 63, 21, 16,    TEXVEC_LINEDW, 63, 18,  4, 
               TEXVEC_LINEDW, 32, 33,  4,    TEXVEC_COLOR,   8,
               TEXVEC_FILL,   31,  5,        TEXVEC_COLOR,  10,  
               TEXVEC_FILL,   33, 35,        TEXVEC_COLOR,  11,
               TEXVEC_FILL,   30, 35,        TEXVEC_EXIT }, 
    /* TEXINDEX_HOLE */
    (char[]) { TEXVEC_COLOR,  13,            TEXVEC_LINESE, 32, 9, 12, 
               TEXVEC_LINESE,  8, 21, 12,    TEXVEC_LINESW, 31, 9, 12, 
               TEXVEC_LINESW, 55, 21, 12,    TEXVEC_LINESE, 32, 12, 9, 
               TEXVEC_LINESE, 14, 21,  9,    TEXVEC_LINESW, 31, 12, 9, 
               TEXVEC_LINESW, 49, 21,  9,    TEXVEC_COLOR,  14, 
               TEXVEC_LINEDW, 31, 13,  4,    TEXVEC_LINESW, 31, 16, 7, 
               TEXVEC_FILL,   30, 14,        TEXVEC_COLOR,  12, 
               TEXVEC_FILL,   32, 11,        TEXVEC_COLOR,  15, 
               TEXVEC_LINEDW, 32, 13,  4,    TEXVEC_LINESE, 32, 16, 7, 
               TEXVEC_FILL,   33, 14,        TEXVEC_COLOR,  16, 
               TEXVEC_FILL,   31, 19,        TEXVEC_EXIT }
};

static void _texture_draw(int t, int x, int y);

/*! \brief Создает изображение и сопутствующие сущности */
static void _image_create(void) {
    display = XOpenDisplay(0);
    window = XCreateSimpleWindow(display, 
                                 RootWindow(display, DefaultScreen(display)), 
                                 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
    image = XCreateImage(display, 
                     DefaultVisual(display, DefaultScreen(display)), 
                     DefaultDepth(display, DefaultScreen(display)),
                     2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
}

/* \brief Обнуляет изображение, заполняя его черным цветом */
static void _image_reset(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++)
            pixdata[y][x] = 0;
}

/*! \brief Конвертирует символ из чертежа в индекс текстуры
 * \param[in] elem Символ чертежа
 * \return Индекс текстуры */
static int _map2texture(char elem) {
    return ((elem >> 4) & 1) << 2 | (elem & 3);
}

/*! \brief Собирает изображение из отдельных тайлов согласно карте */
static void _image_compile(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            _texture_draw(_map2texture(mapdata[y][x]), x, y);
}

/*! \brief Рисует изображение на экране */
static void _image_draw(void) {
    XPutImage(display, window, 
              DefaultGC(display, DefaultScreen(display)), 
              image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
    XMapWindow(display, window);
    XFlush(display);
}

/*! \brief Рисует отверстия на печатной плате */
static void _image_drill(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    _texture_draw(TEXINDEX_HOLE, x, y);
}

/*! \brief Применяет шейдер LCD-эффекта на изображение
 * \param[in] x X-координата изображения
 * \param[in] y Y-координата изображения */
static void _shader_lcd(int x, int y) {
    pixdata[y][x] &= 0xe0e0e0 | (31 << ((x % 3) << 3));
}

/*! \brief Применяет шейдер случайного шума на изображение
 * \param[in] x X-координата изображения
 * \param[in] y Y-координата изображения */
static void _shader_noise(int x, int y) {
    pixdata[y][x] += 0x0f0f0f & (random *= 16777619);
}

/*! \brief Накладывает на изображение различные эффекты */
static void _image_postprocess(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++) {
            _shader_lcd(x, y);
            _shader_noise(x, y);
        }
}

/*! \brief Отрисовывает текстуру на главном холсте по указанным координатам
 * \param[in] t Индекс текстуры
 * \param[in] x X координата тайла
 * \param[in] y Y координата тайла */
static void _texture_draw(int t, int x, int y) {
    for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
        for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
            if (textures[t][ty][tx])
                pixdata[ty + 
                        y * (TEXTURE_TOP_HEIGHT / 2) + 
                        x * (TEXTURE_TOP_HEIGHT / 2)]
                       [tx + 
                        IMAGE_SHIFTX + 
                        x * (TEXTURE_TOP_WIDTH / 2) - 
                        y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}

/*! \brief Производит закраску области текстуры
 * \param[in] t Индекс текстуры
 * \param[in] x X-координата начала
 * \param[in] y Y-координата начала
 * \param[in] source Исходный цвет
 * \param[in] target Новый цвет */
static void _texture_fill(int t, int x, int y, int source, int target) {
    if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT || 
         x < 0 || y < 0) || 
         (textures[t][y][x] == target) || 
         (textures[t][y][x] != source))
        return;
    textures[t][y][x] = target;
    _texture_fill(t, x - 1, y, source, target);
    _texture_fill(t, x + 1, y, source, target);
    _texture_fill(t, x, y - 1, source, target);
    _texture_fill(t, x, y + 1, source, target);
}

/*! \brief Рисует изометрическую линию по направлению SE
 * \param[in] t Индекс текстуры
 * \param[in] x X-координата начала
 * \param[in] y Y-координата начала
 * \param[in] c Длина линии по короткой стороне
 * \param[in] color Цвет рисования */
static void _texture_linese(int t, int x, int y, int c, int color) {
    while (c--) {
        textures[t][y][x++] = color;
        textures[t][y++][x++] = color;
    }
}

/*! \brief Рисует изометрическую линию по направлению SW
 * \param[in] t Индекс текстуры
 * \param[in] x X-координата начала
 * \param[in] y Y-координата начала
 * \param[in] c Длина линии по короткой стороне
 * \param[in] color Цвет рисования */
static void _texture_linesw(int t, int x, int y, int c, int color) {
    while (c--) {
        textures[t][y][x--] = color;
        textures[t][y++][x--] = color;
    }
}

/*! \brief Рисует линию вниз
 * \param[in] t Индекс текстуры
 * \param[in] x X-координата начала
 * \param[in] y Y-координата начала
 * \param[in] c Длина линии
 * \param[in] color Цвет рисования */
static void _texture_linedown(int t, int x, int y, int c, int color) {
    while (c--)
        textures[t][y++][x] = color;
}

/*! \brief Читает данные файла-чертежа и загружает их в карту 
 * \param[in] filename Имя файла-чертежа */
static void _map_read(const char * filename) {
    int f = open(filename, 0);
    read(f, mapdata, MAP_FILEDATA);
    close(f);
}

/*! \brief Заменяет иллюстративные входы из файла-конфигурации на вход
 * в виде провода чтобы работала логика распространения фронта волны */
static void _map_wire_inputs(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            if ((x % 14 == 2) && (y % 4 == 3))
                mapdata[y][x] = MAPCHAR_WIRE;
}

/*! \brief Производит заливку проводника нужным состоянием
 * \param[in] t Игнорируется, артефакт автогенерации кода 
 * \param[in] x X-координата заливки
 * \param[in] y Y-координата заливки
 * \param[in] c Исходное состояние
 * \param[in] l Целевое состояние */
static void _map_fill(int t, int x, int y, int c, int l) {
    if ((x >= MAP_WIDTH || y >= MAP_HEIGHT || 
         x < 0 || y < 0) || (mapdata[y][x] == l)
        || (mapdata[y][x] != c))
        return;
    mapdata[y][x] = l;
    _map_fill(t, x - 1, y, c, l);
    _map_fill(t, x + 1, y, c, l);
    _map_fill(t, x, y - 1, c, l);
    _map_fill(t, x, y + 1, c, l);
}

/*! \brief Включает соответствующие входы схемы в зависимости от значения
 * счетчика.
 * \param[in] counter Счетчик */
static void _map_wire_counter(int counter) {
    _map_fill(0, 2, 3,  mapdata[3][2],  counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 7,  mapdata[7][2],  counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/*! \brief Проводит расчет выходного (результирующего) тока после NOR-узла */
static void _map_process_gates(void) {       
    for (int i = 0; i < MAP_ITERATIONS; i++)
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if (mapdata[y][x] == MAPCHAR_NOR)
                    _map_fill(0, x + 1, y, mapdata[y][x + 1],
                        !(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
                       || mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ? 
                            MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/* Код до рефакторинга */

int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };

int main(int argc, char * args[]) {
    _image_create();

    for (int tex = 0; tex < TEXTURE_COUNT; tex++) {
        char * ptr = vecdata[tex];
        int c = 0;
        while (*ptr != TEXVEC_EXIT) {
            switch (*ptr) {
            case TEXVEC_LINESE:
                _texture_linese(tex, ptr[1], ptr[2], ptr[3], c);
                ptr += 4;
                break;
            case TEXVEC_LINESW:
                _texture_linesw(tex, ptr[1], ptr[2], ptr[3], c);
                ptr += 4;
                break;
            case TEXVEC_LINEDW:
                _texture_linedown(tex, ptr[1], ptr[2], ptr[3], c);
                ptr += 4;
                break;
            case TEXVEC_FILL:
                _texture_fill(tex, ptr[1], ptr[2], 0, c);
                ptr += 3;
                break;
            case TEXVEC_REPEAT:
                ptr = vecdata[ptr[1]];
                break;
            case TEXVEC_COLOR:
                c = _x[ptr[1] / 4] - 1643277 * (ptr[1] % 4);
                ptr += 2;
                break;
            }
        }
    }
    unsigned int counter = 1;
    while (counter++) {
        _map_read(args[ARG_BLUEPRINT]);
        _map_wire_inputs();
        _map_wire_counter(counter);
        _map_process_gates();
        
        _image_reset();          
        _image_compile();
        _image_drill();
        _image_postprocess();        
        _image_draw();
        
        sleep(1);
    } 
    return 0;
}


Максимальное число, которое стоит после инструкции «TEXVEC_COLOR» — это 16. Напишем простейший код, чтобы получить всю таблицу:

Теперь, имея на руках палитру в расшифрованном виде мы можем заменить функцию её использования и написать расшифровки для цветов в константной таблице, а заодно и выделить функцию создания текстур:
Полный код после рефакторинга:
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

/* Код после рефакторинга */

/*! \brief Ширина изображения в пикселях */
#define IMAGE_WIDTH (1220)
/*! \brief Высота изображения в пикселях */
#define IMAGE_HEIGHT (616)
/*! \brief Сдвиг верхней грани карты от левой стороны */
#define IMAGE_SHIFTX (580)

/*! \brief Количество текстур */
#define TEXTURE_COUNT (8)
/*! \brief Ширина текстуры в пикселях */
#define TEXTURE_WIDTH (64)
/*! \brief Высота текстур в пикселях */
#define TEXTURE_HEIGHT (40)
/*! \brief Ширина грани текстуры в пикселях */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief Высота грани текстуры в пикселях */
#define TEXTURE_TOP_HEIGHT (32)

/*! \brief Ширина эмулируемого поля */
#define MAP_WIDTH (19)
/*! \brief Высота эмулируемого поля */
#define MAP_HEIGHT (19)
/*! \brief Количество данные в файле-чертеже. Один байт добавлен для символа '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief Количество итераций во время расчета NOR-узлов */
#define MAP_ITERATIONS (20)

/*! \brief Содержит структуры синтаксиса файла-конфигурации */
enum map_characters {
    MAPCHAR_WIRE  = '.', /**< Провод            (ASCII = 46) */
    MAPCHAR_PLUS  = '+', /**< Провод (есть ток) (ASCII = 43) */
    MAPCHAR_MINUS = '-', /**< Провод (нет тока) (ASCII = 45) */
    MAPCHAR_NOR   = '>', /**< NOR-элемент       (ASCII = 62) */
    MAPCHAR_EMPTY = ' ', /**< Пустой блок       (ASCII = 32) */
};

/*! \brief Содержит индексы текстур */
enum textures_indexes {
    TEXINDEX_EMPTY = (0), /**< Индекс пустой текстуры                 */
    TEXINDEX_MINUS = (1), /**< Индекс текстуры "выключенного провода" */
    TEXINDEX_WIRE  = (2), /**< Индекс текстуры нейтрального провода   */
    TEXINDEX_PLUS  = (3), /**< Индекс текстуры "включенного" провода  */
    /**/
    TEXINDEX_NOR   = (6), /**< Индекс текстуры NOR-элемента           */
    TEXINDEX_HOLE  = (7)  /**< Индекс текстуры отверстия на плате     */
};

/*! \brief Список инструкций векторного интерпретатора */
enum textures_instructions {
    TEXVEC_LINESE = (0), /**< Линия SE                          */
    TEXVEC_LINESW = (1), /**< Линия SW                          */
    TEXVEC_LINEDW = (2), /**< Линия вниз                        */
    TEXVEC_FILL   = (3), /**< Заливка                           */
    TEXVEC_EXIT   = (4), /**< Конец списка инструкций           */
    TEXVEC_REPEAT = (5), /**< Повтор инструкций другой текстуры */
    TEXVEC_COLOR  = (6)  /**< Выбор цвета                       */
};

/*! \brief Аргументы программы */
enum program_arguments { 
    ARG_PROGRAM,  /**< Имя самой программы */
    ARG_BLUEPRINT /**< Имя файла-чертежа   */
};

/*! \brief Бинарные данные пикселей изображения.
 * Типизированы к int для оперирования пикселями вместо каналов */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief Текстуры блоков, отображаемых на поле */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief Данные эмулируемого поля. 
 * Один байт добавлен для упрощения обработки символа '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];
/*! \brief Зерно генератора случайных чисел */
int random = 2166136261;

/*! \brief Экземпляр дисплея Xlib */
Display * display;
/*! \brief Экземпляр главного окна Xlib */
Window window;
/*! \brief Изображение для вывода на экран */
XImage * image;

/*! \brief Палитра цветов для векторной отрисовки 
 * \note Черный имеет цвет {001} для отличия от "прозрачного" черного {000} */
static const int texturepalette[] = { 
                         /*  Светлее   ▁▁▂▂▃▃▄▄▅▅▆▆▇▇██   Темнее */    
    /* Светло-коричневый */ 0xe6ac73, 0xcd9966, 0xb48659, 0x9b734c,
    /* Темно-коричневый  */ 0x806040, 0x674d33, 0x4e3a26, 0x352719,
    /* Зеленый           */ 0x59b368, 0x40a05b, 0x278d4e, 0x0e7a41,
    /* Серый             */ 0xc6c6c6, 0xadb3b9, 0x94a0ac, 0x7b8d9f,
    /* Черный            */ 0x000001
};

/*! \brief Векторные инструкции для рисования текстур */
static const char * vecdata[TEXTURE_COUNT] = { 
    /* TEXINDEX_EMPTY */
    (char[]) { TEXVEC_EXIT }, 
    /* TEXINDEX_MINUS */
    (char[]) { TEXVEC_COLOR,   5,            TEXVEC_LINESE, 32,  5, 16, 
               TEXVEC_LINESE,  0, 21, 16,    TEXVEC_LINESW, 63, 21, 16, 
               TEXVEC_LINEDW,  0, 21,  4,    TEXVEC_LINEDW, 31, 36,  4, 
               TEXVEC_LINESW, 31,  5, 16,    TEXVEC_LINESE,  0, 24, 16, 
               TEXVEC_LINESW, 63, 24, 16,    TEXVEC_LINEDW, 63, 21,  4, 
               TEXVEC_LINEDW, 32, 36,  4,    TEXVEC_COLOR,   4, 
               TEXVEC_FILL,   31, 8,         TEXVEC_COLOR,   6,
               TEXVEC_FILL,   33, 38,        TEXVEC_COLOR,   7, 
               TEXVEC_FILL,   30, 38,        TEXVEC_EXIT },
    /* TEXINDEX_WIRE */
    (char[]) { TEXVEC_REPEAT,  1 }, 
    /* TEXINDEX_PLUS */
    (char[]) { TEXVEC_COLOR,   1,            TEXVEC_LINESE, 32,  5, 16,
               TEXVEC_LINESE,  0, 21, 16,    TEXVEC_LINESW, 63, 21, 16, 
               TEXVEC_LINEDW, 63, 21,  4,    TEXVEC_LINEDW, 31, 36,  4, 
               TEXVEC_LINESW, 31,  5, 16,    TEXVEC_LINESE,  0, 24, 16, 
               TEXVEC_LINESW, 63, 24, 16,    TEXVEC_LINEDW, 63, 21,  4, 
               TEXVEC_LINEDW, 32, 36,  4,    TEXVEC_COLOR,   0, 
               TEXVEC_FILL,   31,  8,        TEXVEC_COLOR,   2,
               TEXVEC_FILL,   33, 38,        TEXVEC_COLOR,   3, 
               TEXVEC_FILL,   30, 38,        TEXVEC_EXIT },
    /* Не используется */
    (char[]) { TEXVEC_EXIT }, 
    /* Не используется */
    (char[]) { TEXVEC_EXIT },
    /* TEXINDEX_NOR */
    (char[]) { TEXVEC_COLOR,   9,            TEXVEC_LINESE, 32,  2, 16, 
               TEXVEC_LINESE,  0, 18, 16,    TEXVEC_LINESW, 63, 18, 16, 
               TEXVEC_LINEDW,  0, 18,  4,    TEXVEC_LINEDW, 31, 33,  4, 
               TEXVEC_LINESW, 31,  2, 16,    TEXVEC_LINESE,  0, 21, 16, 
               TEXVEC_LINESW, 63, 21, 16,    TEXVEC_LINEDW, 63, 18,  4, 
               TEXVEC_LINEDW, 32, 33,  4,    TEXVEC_COLOR,   8,
               TEXVEC_FILL,   31,  5,        TEXVEC_COLOR,  10,  
               TEXVEC_FILL,   33, 35,        TEXVEC_COLOR,  11,
               TEXVEC_FILL,   30, 35,        TEXVEC_EXIT }, 
    /* TEXINDEX_HOLE */
    (char[]) { TEXVEC_COLOR,  13,            TEXVEC_LINESE, 32, 9, 12, 
               TEXVEC_LINESE,  8, 21, 12,    TEXVEC_LINESW, 31, 9, 12, 
               TEXVEC_LINESW, 55, 21, 12,    TEXVEC_LINESE, 32, 12, 9, 
               TEXVEC_LINESE, 14, 21,  9,    TEXVEC_LINESW, 31, 12, 9, 
               TEXVEC_LINESW, 49, 21,  9,    TEXVEC_COLOR,  14, 
               TEXVEC_LINEDW, 31, 13,  4,    TEXVEC_LINESW, 31, 16, 7, 
               TEXVEC_FILL,   30, 14,        TEXVEC_COLOR,  12, 
               TEXVEC_FILL,   32, 11,        TEXVEC_COLOR,  15, 
               TEXVEC_LINEDW, 32, 13,  4,    TEXVEC_LINESE, 32, 16, 7, 
               TEXVEC_FILL,   33, 14,        TEXVEC_COLOR,  16, 
               TEXVEC_FILL,   31, 19,        TEXVEC_EXIT }
};

static void _texture_draw(int t, int x, int y);

/*! \brief Создает изображение и сопутствующие сущности */
static void _image_create(void) {
    display = XOpenDisplay(0);
    window = XCreateSimpleWindow(display, 
                                 RootWindow(display, DefaultScreen(display)), 
                                 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
    image = XCreateImage(display, 
                     DefaultVisual(display, DefaultScreen(display)), 
                     DefaultDepth(display, DefaultScreen(display)),
                     2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
}

/* \brief Обнуляет изображение, заполняя его черным цветом */
static void _image_reset(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++)
            pixdata[y][x] = 0;
}

/*! \brief Конвертирует символ из чертежа в индекс текстуры
 * \param[in] elem Символ чертежа
 * \return Индекс текстуры */
static int _map2texture(char elem) {
    return ((elem >> 4) & 1) << 2 | (elem & 3);
}

/*! \brief Собирает изображение из отдельных тайлов согласно карте */
static void _image_compile(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            _texture_draw(_map2texture(mapdata[y][x]), x, y);
}

/*! \brief Рисует изображение на экране */
static void _image_draw(void) {
    XPutImage(display, window, 
              DefaultGC(display, DefaultScreen(display)), 
              image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
    XMapWindow(display, window);
    XFlush(display);
}

/*! \brief Рисует отверстия на печатной плате */
static void _image_drill(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    _texture_draw(TEXINDEX_HOLE, x, y);
}

/*! \brief Применяет шейдер LCD-эффекта на изображение
 * \param[in] x X-координата изображения
 * \param[in] y Y-координата изображения */
static void _shader_lcd(int x, int y) {
    pixdata[y][x] &= 0xe0e0e0 | (31 << ((x % 3) << 3));
}

/*! \brief Применяет шейдер случайного шума на изображение
 * \param[in] x X-координата изображения
 * \param[in] y Y-координата изображения */
static void _shader_noise(int x, int y) {
    pixdata[y][x] += 0x0f0f0f & (random *= 16777619);
}

/*! \brief Накладывает на изображение различные эффекты */
static void _image_postprocess(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++) {
            _shader_lcd(x, y);
            _shader_noise(x, y);
        }
}

/*! \brief Отрисовывает текстуру на главном холсте по указанным координатам
 * \param[in] t Индекс текстуры
 * \param[in] x X координата тайла
 * \param[in] y Y координата тайла */
static void _texture_draw(int t, int x, int y) {
    for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
        for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
            if (textures[t][ty][tx])
                pixdata[ty + 
                        y * (TEXTURE_TOP_HEIGHT / 2) + 
                        x * (TEXTURE_TOP_HEIGHT / 2)]
                       [tx + 
                        IMAGE_SHIFTX + 
                        x * (TEXTURE_TOP_WIDTH / 2) - 
                        y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}

/*! \brief Производит закраску области текстуры
 * \param[in] t Индекс текстуры
 * \param[in] x X-координата начала
 * \param[in] y Y-координата начала
 * \param[in] source Исходный цвет
 * \param[in] target Новый цвет */
static void _texture_fill(int t, int x, int y, int source, int target) {
    if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT || 
         x < 0 || y < 0) || 
         (textures[t][y][x] == target) || 
         (textures[t][y][x] != source))
        return;
    textures[t][y][x] = target;
    _texture_fill(t, x - 1, y, source, target);
    _texture_fill(t, x + 1, y, source, target);
    _texture_fill(t, x, y - 1, source, target);
    _texture_fill(t, x, y + 1, source, target);
}

/*! \brief Рисует изометрическую линию по направлению SE
 * \param[in] t Индекс текстуры
 * \param[in] x X-координата начала
 * \param[in] y Y-координата начала
 * \param[in] c Длина линии по короткой стороне
 * \param[in] color Цвет рисования */
static void _texture_linese(int t, int x, int y, int c, int color) {
    while (c--) {
        textures[t][y][x++] = color;
        textures[t][y++][x++] = color;
    }
}

/*! \brief Рисует изометрическую линию по направлению SW
 * \param[in] t Индекс текстуры
 * \param[in] x X-координата начала
 * \param[in] y Y-координата начала
 * \param[in] c Длина линии по короткой стороне
 * \param[in] color Цвет рисования */
static void _texture_linesw(int t, int x, int y, int c, int color) {
    while (c--) {
        textures[t][y][x--] = color;
        textures[t][y++][x--] = color;
    }
}

/*! \brief Рисует линию вниз
 * \param[in] t Индекс текстуры
 * \param[in] x X-координата начала
 * \param[in] y Y-координата начала
 * \param[in] c Длина линии
 * \param[in] color Цвет рисования */
static void _texture_linedown(int t, int x, int y, int c, int color) {
    while (c--)
        textures[t][y++][x] = color;
}

/*! \brief Создает все текстуры, интерпретатор векторных инструкций */
static void _textures_create(void) {
    for (int tex = 0; tex < TEXTURE_COUNT; tex++) {
        const char * ptr = vecdata[tex];
        int c = 0;
        while (*ptr != TEXVEC_EXIT) {
            switch (*ptr) {
            case TEXVEC_LINESE:
                _texture_linese(tex, ptr[1], ptr[2], ptr[3], c);
                ptr += 4;
                break;
                
            case TEXVEC_LINESW:
                _texture_linesw(tex, ptr[1], ptr[2], ptr[3], c);
                ptr += 4;
                break;
                
            case TEXVEC_LINEDW:
                _texture_linedown(tex, ptr[1], ptr[2], ptr[3], c);
                ptr += 4;
                break;
                
            case TEXVEC_FILL:
                _texture_fill(tex, ptr[1], ptr[2], 0, c);
                ptr += 3;
                break;
                
            case TEXVEC_REPEAT:
                ptr = vecdata[ptr[1]];
                break;
                
            case TEXVEC_COLOR:
                c = texturepalette[ptr[1]];
                ptr += 2;
                break;
            }
        }
    }
}

/*! \brief Читает данные файла-чертежа и загружает их в карту 
 * \param[in] filename Имя файла-чертежа */
static void _map_read(const char * filename) {
    int f = open(filename, 0);
    read(f, mapdata, MAP_FILEDATA);
    close(f);
}

/*! \brief Заменяет иллюстративные входы из файла-конфигурации на вход
 * в виде провода чтобы работала логика распространения фронта волны */
static void _map_wire_inputs(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            if ((x % 14 == 2) && (y % 4 == 3))
                mapdata[y][x] = MAPCHAR_WIRE;
}

/*! \brief Производит заливку проводника нужным состоянием
 * \param[in] t Игнорируется, артефакт автогенерации кода 
 * \param[in] x X-координата заливки
 * \param[in] y Y-координата заливки
 * \param[in] c Исходное состояние
 * \param[in] l Целевое состояние */
static void _map_fill(int t, int x, int y, int c, int l) {
    if ((x >= MAP_WIDTH || y >= MAP_HEIGHT || 
         x < 0 || y < 0) || (mapdata[y][x] == l)
        || (mapdata[y][x] != c))
        return;
    mapdata[y][x] = l;
    _map_fill(t, x - 1, y, c, l);
    _map_fill(t, x + 1, y, c, l);
    _map_fill(t, x, y - 1, c, l);
    _map_fill(t, x, y + 1, c, l);
}

/*! \brief Включает соответствующие входы схемы в зависимости от значения
 * счетчика.
 * \param[in] counter Счетчик */
static void _map_wire_counter(int counter) {
    _map_fill(0, 2, 3,  mapdata[3][2],  counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 7,  mapdata[7][2],  counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/*! \brief Проводит расчет выходного (результирующего) тока после NOR-узла */
static void _map_process_gates(void) {       
    for (int i = 0; i < MAP_ITERATIONS; i++)
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if (mapdata[y][x] == MAPCHAR_NOR)
                    _map_fill(0, x + 1, y, mapdata[y][x + 1],
                        !(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
                       || mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ? 
                            MAPCHAR_PLUS : MAPCHAR_MINUS);
}

int main(int argc, char * args[]) {
    _image_create();
    _textures_create();
    
    unsigned int counter = 1;
    while (counter++) {
        _map_read(args[ARG_BLUEPRINT]);
        _map_wire_inputs();
        _map_wire_counter(counter);
        _map_process_gates();
        
        _image_reset();          
        _image_compile();
        _image_drill();
        _image_postprocess();        
        _image_draw();
        
        sleep(1);
    } 
    return 0;
}


Эпилог


Вот и всё. Несмотря на то, что я не занял никаких призовых мест, это был достаточно любопытный опыт (умерший за два дня до начала приема работ HDD этому поспособствовал). Было что-то неправильное в том, чтобы писать код, максимально не читаемый и одновременно абсолютно валидный с точки зрения языка. Однако нельзя сказать, что это было неинтересно. Когда утилита, подсчитывающая токены говорит, что код нарушает правила превышая лимит на 2000+ токенов, а ты не знаешь, как его сократить — это вызов. Когда размер файла превышает лимиты, а ты хочешь добавить какой-то графический эффект — это вызов. Это было трудно, вместить столько функционала, и тем слаще было читать вывод утилиты, которая после нескольких сотен исправлений наконец-таки сказала, что код можно выгружать. Я бы порекомендовал читателям поучаствовать в конкурсе хотя бы просто для того, чтобы приобщиться и испытать свои силы. Да, никаких наград или призов это не дает, но зато вы будете знать, что под ником zhestokyshveller на сайте IOCCC скрываетесь вы.

Let's block ads! (Why?)

Комментариев нет:

Отправить комментарий