- Comment j'ai participé à IOCCC-'19 (et perdu). Partie 1: "Tic-tac-toe"
- Comment j'ai participé à IOCCC-'19 (et perdu). Partie 2: "NOR Simulator"
J'espère que cet article vous aidera lors de l'analyse du code ou du code de quelqu'un d'autre après un décompilateur ou un obfuscateur.
Si vous ne savez toujours pas ce qu'est IOCCC ou si vous souhaitez vous familiariser avec une version plus simple du code obscurci, je vous recommande de vous référer à la première partie.
À tous les autres, je vous souhaite une agréable lecture.
Toutes les sources sont placées sur github , d'où vous pouvez les télécharger et essayer de les compiler.
Donnée initiale
Puisque le code source sous forme de texte peut être trouvé sur le lien, je vais montrer à quoi ressemble le code graphiquement:
Traditionnellement, des "points supplémentaires" sont donnés si le code est formaté non standard ou ressemble à une sorte d'image. Eh bien, supposons que tout va bien ici.
Mais que fait le programme?
Il initialise la pile graphique du serveur X, scanne le fichier de configuration fourni, dessine un schéma électrique en fonction du fichier et démarre la simulation, en changeant alternativement la polarité sur les 4 broches d'entrée, en utilisant uniquement des éléments NOR (Not-OR). Le rendu se fait avec l'ancien shader d'écran LCD.
Le programme est livré avec plusieurs fichiers de configuration, à savoir:
DIP8-4packnot.txt - un analogue approximatif du CMOS 4041 / onduleur à quatre canaux
(L'image est compressée en 2 fois pour s'adapter aux limites de la décence. C'est en fait drôle que le programme, pesant 3,5 Ko, génère une série d'images qui prennent jusqu'à 10,5 Mo en compression maximale)
DIP8-triplexor.txt - un analogue approximatif du CMOS 4030 avec entrées combinées et trois canaux / Porte XOR à trois canaux avec entrées combinées
DIP8-fulladder.txt - un analogue approximatif du CMOS 4008, mais pour deux bits / additionneur pour 2 bits avec une sortie de bit de report
Analyser le code
La tâche la plus difficile cette fois-ci était de s'adapter à la taille limite du travail soumis. Non seulement la taille du fichier est limitée, mais également le nombre de "jetons" conditionnels - symboles d'opération, mots-clés de langue et paires de parenthèses. C'est pour "exploiter" cette fonctionnalité de l'analyseur-vérificateur de taille dans le programme qu'un grand nombre de définitions sont déclarées, qui réduisent les blocs de code à un seul mot-clé C.
Tout d'abord, regardons dans le Makefile pour comprendre comment le code est assemblé:
#!/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}
Comme vous pouvez le voir, ce travail, tout comme le précédent, utilise activement les appels système pour éviter les "#include" laids qui cassent le modèle de l'image. Souvenons-nous de ce fait et préparons une ligne pour le préprocesseur et le linter:
Après le préprocesseur
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;
}
Eh bien, nous avons rempli au moins une des conditions de la concurrence, le code après le préprocesseur n'est pas devenu plus clair.
Commençons par ce que vous pouvez attraper en un coup d'œil et essayez de reconstruire la chaîne d'événements.
dlsym \ dlopen
Évidemment, pour utiliser les fonctions du serveur X et créer une fenêtre, puis y rendre quelque chose, le code doit se tourner vers la bibliothèque XLib. Le code contient des fonctions dlopen / dlsym qui vous permettent de charger dynamiquement la bibliothèque, mais elles sont alimentées par un désordre délicat à l'entrée:
char _n[] =
"pu~D--2os" "<<<<<<<<" "<<<DSlyrXuolp}e" "<<<<<<<<"
"D_ny}hyOuqlpyKurxsk<D_ny" "}hyUq}{y" "<<<<<<<<" "DLihUq}{y" "<<<<<<<<"
"<<<DQ}lKurxsk" "<<<<<<<<" "<<DZpiot<";
...
T = dlopen(_n, 2);
Prenons du recul et inspectons le code suivant:
int h = 127;
while (h--) {
_n[h] ^= 28;
_n[h] -= (_n[h] == 32 ? 32 : 0);
}
Apparemment, cela transforme le tableau d'origine d'une certaine manière, nous permettant d'obtenir des lignes lisibles. Exécutons-le séparément:
https://onlinegdb.com/SJNM9Og7v :
libX11.so
XOpenDisplay
XCreateSimpleWindow
XCreateImage
XPutImage
XMapWindow
XFlush
Pour appeler des fonctions de format si différent sur une seule ligne, le code exploite le fait que dans le langage C standard (void) signifie pas de paramètres, et () signifie n'importe quel nombre de paramètres. Il ne reste plus qu'à convertir le vide * résultant dans le type correspondant ((long (*) ()) et voila:
w = ((long (*)()) dlsym(T, _n + (2 * 20))) (d, (*(long *)((char *) (*(long *)((char *) d + 232)) + 16))
Sachant ce que signifient ces conversions, nous pouvons maintenant remplacer cette utilisation inhabituelle de dlsym par des chaînes:
Après avoir remplacé les lignes:
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;
}
Et puis aux fonctions natives:
Après remplacement par des fonctions `` natives '':
#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;
}
Appels système
Remplaçons les appels système de la même manière que nous avons suivi dans la première partie:
Code sans appels système:
#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 et décalages
Essayons de démonter la construction suivante:
w = XCreateSimpleWindow(d, (*(long *) ((char *) (*(long *) ((char *)d + 232)) + 16)), 0, 0, 1220, 616, 1, 0, 0);
Un tas de conversions de type, qui, à première vue, ne sont nécessaires que pour confondre le lecteur, mais chaque conversion a ici son propre but, à savoir:
d est un pointeur vers une structure Display dans le contexte Xlib. Il a un champ de tableau appelé screens et pour obtenir un pointeur vers le premier élément de ce tableau, nous devons compter un certain nombre d'octets (x64 - 232) à partir du pointeur d'affichage vers l'avant. Puisque Display n'est pas char *, alors avec la lecture directe, nous aurions calculé en sizeof (long *) octets. Nous convertissons donc d en char * et déplaçons 232 octets:
((char *)d + 232)
Nous avons obtenu la position du premier élément Screens en mémoire. Convertissons-le en un pointeur à part entière et déréférencons-le:
(*(long *) ((char *)d + 232))
Maintenant, dans la structure Screens, nous devons obtenir un pointeur vers la fenêtre racine, Root. Pour ce faire, éloignons-nous des écrans de 16 octets et déréférencons la construction:
(*(long *) ((char *) (*(long *) ((char *)d + 232)) + 16))
Cette construction est en fait utilisée quotidiennement par les programmeurs Xlib, puisque son équivalent couramment utilisé est
RootWindow(Display, DefaultScreen(Display))
De la même manière, nous remplacerons les décalages correspondants à d'autres endroits afin d'obtenir des macros plus familières (en même temps, nous corrigerons les jambages de retrait):
Code après remplacement des décalages:
#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;
}
Données d'image
Notez que XCreateImage nécessite un pointeur vers la zone mémoire où les données de pixels seront stockées. Pour notre appel de fonction, il s'agit de la variable "x_". Renommez-le pixdata et trouvez tous les endroits où il est utilisé:
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);
}
Isolons le bloc pixdata [..] = 0 dans une fonction séparée et essayons de comprendre ce que fait la première occurrence:
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];
Si vous regardez attentivement l'image finale générée pendant le fonctionnement du programme, vous remarquerez facilement que 40 et 64 sont les dimensions d'un "bloc" séparé à partir duquel le circuit est construit.
Par conséquent, cette fonction dessine une «tuile» séparée sur le canevas de l'image principale, et à en juger par l'indexation du tableau «_», la variable «t» est responsable de l'index de l'image, et p et q - pour les coordonnées x et y. Renommez également "_" en textures:
Le code pour le moment:
#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;
}
Lire la carte
Séparons les lignes open..close dans une fonction séparée, où le contenu du fichier sélectionné est lu dans la variable m (que nous renommerons mapdata).
Pourquoi le fichier est-il compté à chaque cycle? C'était plus court en termes de code et de jetons. Le processus de "pilonnage" du code a pris environ 4 jours pour entrer dans les limites des règles. Si vous ne lisez le fichier qu'une seule fois, vous aurez besoin de stockage supplémentaire et d'un analogue de la fonction memcpy.
Fonction dédiée _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;
}
Puisque nous avons touché à la variable mapdata, prêtons attention aux lignes et aux fonctions où elle change - c'est la fonction "b", que nous n'allons pas toucher pour l'instant, et "main" où, en faisant attention au contenu des fichiers de configuration "complets", nous refactoriserons:
Après refactoring sur 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;
}
Afin de terminer le traitement du travail avec "mapdata", vous devez répondre à deux autres questions - qu'est-ce que la fonction "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);
}
Et ce qui se passe dans le bloc:
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);
Fonction "b"
Si vous regardez de près la fonction "b", vous remarquerez qu'elle est douloureusement similaire à l'implémentation de l'algorithme flood_fill , qui coïncide avec son objectif théorique - il "inonde" le "fil" avec l'état souhaité, permettant au front d'onde actuel de se propager à l'extrémité du fil. Renommons-le et plaçons-le dans le bloc «prêt pour la production».
Remplissage d'inondation
#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;
}
Bloc étrange
Il reste maintenant à analyser ce qui se passe dans la ligne:
_texture_draw(((mapdata[y][x] >> 4) & 1) << 2 | (mapdata[y][x] & 3), x, y);
Puisque nous avons déjà construit une table complète des états qui peuvent être à l'intérieur des données de la carte, nous pouvons obtenir toutes les valeurs de sortie du premier paramètre:
énumération | int | Résultat |
---|---|---|
MAPCHAR_WIRE | 46 | 2 |
MAPCHAR_PLUS | 43 | 3 |
MAPCHAR_MINUS | 45 | 1 |
MAPCHAR_NOR | 62 | 6 |
MAPCHAR_EMPTY | 32 | 0 |
Ouais, c'est-à-dire qu'à la suite de cette transformation, nous obtenons l'indice de texture dans le tableau de texture.
Il a fallu quelques heures pour réfléchir au mécanisme de génération d'un ensemble de symboles lisibles et compréhensibles de manière associative en index de texture. J'ai écrit les symboles qui pourraient signifier des fils et des éléments NOR, puis, après avoir peint leurs valeurs binaires, j'ai encerclé les zones uniques. En plus de l'actuelle, il y avait une deuxième option avec des calculs plus complexes, mais elle est plus longue, par conséquent, elle ne correspondait pas à la limite de jetons.
Génial, cela nous donne la possibilité d'isoler une autre fonction et de déclarer une énumération pour chaque texture:
Après un autre refactoring:
#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;
}
Texture n ° 7
Si vous regardez attentivement le tableau "z", vous remarquerez qu'il contient 8 blocs de données comme constante pour le nombre de textures. Et il a même deux espaces aux positions 4 et 5, tout comme dans notre énumération, il s'agit probablement de données de texture. Cependant, il contient 8 images, et nous n'avons pu "ouvrir" que 7. Cependant, si nous sommes suffisamment prudents, nous pouvons remarquer qu'il existe un morceau de code qui dessine spécifiquement la 7ème texture:
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);
Par la position, vous pouvez déjà deviner de quoi il s'agit, mais commentons ces lignes et exécutons l'application:
Avant:
Après:
Nous savons maintenant avec certitude qu'il s'agit de la texture du trou sur la carte et pouvons l'ajouter à la liste d'énumération en la rendant dans une fonction séparée:
Toutes les textures assemblées:
#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;
}
Shaders
Les chats de l'article précédent ont promis des shaders. Et ils sont ici. Et où est le code responsable de leur traitement?
_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(); //
Par la méthode d'élimination, on comprend que le bruit de l'écran et l'effet du moniteur LCD donnent ces deux lignes. Comment travaillent-ils?
Commençons par le dernier:
pixdata[y][x] += 986895 & (rn *= 16777619);
À chaque pixel est ajoutée la valeur 986895 (qui dans les versions hexadécimales ressemble à 0x0f0f0f), qui était auparavant au moyen de l'opération bit-AND combinée avec le résultat de la multiplication de rn par 16777619. Si rn était un générateur de nombres aléatoires, cela créerait un "bruit" granuleux sur l'écran dans les 16 gradations pour chaque canal. Et puisque le bruit apparaît, alors rn est le générateur de nombres aléatoires. Mais comment y parvenir?
int rn = 2166136261;
Au tout début du programme, la variable rn est initialisée avec le numéro 2166136261. Et à chaque itération, le pixel est multiplié par 16777619. Ce n'est rien de plus qu'un générateur de nombres pseudo-aléatoires. Mais au lieu d'un générateur linéaire bien étudié, l'algorithme de hachage FNV sans étape XOR est utilisé, car nous n'avons pas besoin du résultat final.
Il reste à voir comment fonctionne la ligne précédente:
pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
Convertissons le nombre 14737632 au format hexadécimal, car nous travaillons avec des canaux lumineux à un octet: 0xe0e0e0. Et maintenant, en prenant x égal de 0 à 3, nous effectuons les calculs correspondants:
0xe0e0e0 | (31 << ((0 % 3) << 3)) = e0e0ff
0xe0e0e0 | (31 << ((1 % 3) << 3)) = e0ffe0
0xe0e0e0 | (31 << ((2 % 3) << 3)) = ffe0e0
Si nous appliquons maintenant ces masques en utilisant l'opération "&" à la couleur d'un pixel, nous obtiendrons, respectivement, des canaux R et V, R et B, V et B muets, qui ressembleront à l'effet d'un moniteur LCD:
Séparons-les en fonctions séparées:
#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"
Il y a encore 4 fonctions que nous n'avons pas étudiées ou renommées - ce sont «e», «k», «r» et «u». Essayons de les inspecter sans chercher les endroits d'où ils sont appelés:
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);
}
De toute évidence, cette fonction ressemble et fonctionne comme flood_fill, uniquement pour le tableau textures, renommons-le en _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;
}
}
Les fonctions "k" et "r" pour chaque unité donnée c dessinent deux pixels avec la valeur de l et se déplacent vers la droite ou la gauche de deux pixels et vers le bas de un - cela signifie que ce sont des fonctions pour dessiner les lignes isométriques SW et SE. Renommons-les en _texture_linesw et _texture_linese.
À ce stade, vous pouvez déjà deviner que la dernière fonction "u" trace une ligne verticalement vers le bas:
void u(int t, int x, int y, int c, int l) {
while (c--)
textures[t][y++][x] = l;
}
Renommons-le en _texture_linedown.
Toutes les fonctions individuelles ont été refactorisées:
#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;
}
Graphiques vectoriels
La dernière étape reste - pour comprendre ce qui se passe dans le dernier boîtier de commutation, laissé pour plus tard:
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;
}
}
}
Maintenant que les fonctions ont de nouveaux noms compréhensibles, on peut dire que ce bloc de code interprète les données du tableau "z", et selon les instructions qu'il contient (par exemple, 0, 5, 5, 8, 2 - "dessine la ligne Sud- Est, à partir de [5,5] 8 pixels de long sur le côté court avec le numéro de couleur 2 ") dessine l'ensemble des textures.
Tout semble clair, mais aucune indication de la couleur dans le programme n'a été remarquée.
c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
Ouais, donc le tableau _x est une palette, mais dans un format très étrange, "compressé".
int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
Comme nous ne savons pas encore combien de couleurs sont utilisées dans la palette (lors du réglage de la couleur, l'index est au moins divisible par 4), nous reformatons la table de données pour le dessin et regroupons les nombres par catégories, en remplaçant les signatures d'instructions par des constantes:
Refactoriser la table d'instructions vectorielles
#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;
}
Le nombre maximum qui se trouve après l'instruction "TEXVEC_COLOR" est 16. Écrivons le code le plus simple pour obtenir la table entière:
maintenant, ayant la palette déchiffrée entre nos mains, nous pouvons remplacer la fonction de son utilisation et écrire des déchiffrements pour les couleurs dans la table constante, et en même temps mettre en évidence la fonction de création de textures:
Code complet après refactoring:
#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;
}
Épilogue
C'est tout.Malgré le fait que je n'ai gagné aucun prix, ce fut une expérience plutôt curieuse (le disque dur décédé deux jours avant le début de l'acceptation du travail y a contribué). Il y avait quelque chose qui n'allait pas dans l'écriture de code qui était aussi illisible que possible et en même temps absolument valable du point de vue de la langue. Cependant, on ne peut pas dire que ce n'était pas intéressant. Quand un utilitaire qui compte les jetons dit que le code enfreint les règles en dépassant la limite de plus de 2000 jetons et que vous ne savez pas comment le raccourcir, c'est un défi. Lorsque la taille du fichier dépasse les limites et que vous souhaitez ajouter une sorte d'effet graphique, c'est un défi. Il était difficile, pour accueillir autant de fonctionnalités, et plus il était doux de lire la sortie de l'utilitaire, qui, après plusieurs centaines de corrections, a finalement déclaré que le code pouvait être déchargé. Je recommanderais aux lecteurs de participer au concours, ne serait-ce que pourpour rejoindre et tester votre force.
Oui, il ne donne pas de récompenses ou de prix, mais vous saurez que vous vous cachez sous le surnom de zhestokyshveller sur le site Web de l'IOCCC.