- Wie ich an IOCCC-'19 teilgenommen habe (und verloren habe). Teil 1: "Tic-Tac-Toe"
- Wie ich an IOCCC-'19 teilgenommen habe (und verloren habe). Teil 2: "NOR Simulator"
Ich hoffe, dieser Artikel hilft Ihnen beim Parsen des Codes oder Codes eines anderen nach einem Dekompiler oder Verschleierer.
Wenn Sie immer noch nicht wissen, was IOCCC ist, oder sich mit einer einfacheren Version des verschleierten Codes vertraut machen möchten, empfehle ich, sich dem ersten Teil zuzuwenden.
Allen anderen wĂŒnsche ich eine angenehme LektĂŒre.
Alle Quellen werden auf Github abgelegt , von wo Sie sie herunterladen und versuchen können, sie zu kompilieren.
Ausgangsdaten
Da der Quellcode in Textform unter dem Link zu finden ist, werde ich zeigen, wie der Code grafisch aussieht:
Traditionell werden "zusÀtzliche Punkte" vergeben, wenn der Code nicht standardisiert formatiert ist oder wie ein Bild aussieht. Nehmen wir an, dass hier alles in Ordnung ist.
Aber was macht das Programm?
Es initialisiert den X-Server-Grafikstapel, scannt die bereitgestellte Konfigurationsdatei, zeichnet ein elektrisches Diagramm gemÀà der Datei und startet die Simulation, wobei abwechselnd die PolaritÀt an den 4 Eingangspins geÀndert wird, wobei nur NOR-Elemente (Not-OR) verwendet werden. Das Rendern erfolgt mit dem alten LCD-Bildschirm-Shader.
Das Programm enthÀlt mehrere Konfigurationsdateien, nÀmlich:
DIP8-4packnot.txt - ein ungefÀhres Analogon des CMOS 4041 / Vierkanal-Wechselrichters
(Das Bild wird zweimal komprimiert, um die Grenzen des Anstands zu erreichen. Es ist eigentlich lustig, dass das Programm mit einem Gewicht von 3,5 KB eine Reihe von Bildern generiert, die bei maximaler Komprimierung 10,5 + MB aufnehmen.)
DIP8-triplexor.txt - ein ungefÀhres Analogon von CMOS 4030 mit kombinierten EingÀngen und drei KanÀlen / Dreikanal-XOR-Gatter mit kombinierten EingÀngen
DIP8-fulladder.txt - ein ungefĂ€hres Analogon von CMOS 4008, jedoch fĂŒr zwei Bits / Addierer fĂŒr 2 Bits mit einem Ăbertragsbitausgang
Code analysieren
Die schwierigste Aufgabe bestand diesmal darin, in die GröĂenbeschrĂ€nkung der eingereichten Arbeiten zu passen. Nicht nur die DateigröĂe ist begrenzt, sondern auch die Anzahl der bedingten "Token" - Operationssymbole, SprachschlĂŒsselwörter und Klammerpaare. Um diese Funktion des GröĂenparser-Checkers im Programm "auszunutzen", wird eine groĂe Anzahl von Definitionen deklariert, die Codeblöcke auf ein einziges C-SchlĂŒsselwort reduzieren.
Schauen wir uns zunÀchst das Makefile an, um zu verstehen, wie der Code zusammengesetzt wird:
#!/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}
Wie Sie sehen können, verwendet diese Arbeit, genau wie die vorherige, aktiv Systemaufrufe, um hĂ€ssliche "#include" zu vermeiden, die das Bildmuster brechen. Erinnern wir uns an diese Tatsache und bereiten eine Zeile fĂŒr den PrĂ€prozessor und den Linter vor:
Nach dem PrÀprozessor
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;
}
Nun, wir haben mindestens eine der Wettbewerbsbedingungen erfĂŒllt, der Code nach dem PrĂ€prozessor wurde nicht klarer.
Beginnen wir mit dem, was Sie auf einen Blick erfassen können, und versuchen Sie, die Ereigniskette zu rekonstruieren.
dlsym \ dlopen
Um die Funktionen des X-Servers nutzen und ein Fenster erstellen und dann etwas darin zeichnen zu können, muss sich der Code natĂŒrlich an die XLib-Bibliothek wenden. Der Code enthĂ€lt dlopen / dlsym-Funktionen, mit denen Sie die Bibliothek dynamisch laden können, aber an der Eingabe wird ihnen eine Art kniffliges Durcheinander zugefĂŒhrt:
char _n[] =
"pu~D--2os" "<<<<<<<<" "<<<DSlyrXuolp}e" "<<<<<<<<"
"D_ny}hyOuqlpyKurxsk<D_ny" "}hyUq}{y" "<<<<<<<<" "DLihUq}{y" "<<<<<<<<"
"<<<DQ}lKurxsk" "<<<<<<<<" "<<DZpiot<";
...
T = dlopen(_n, 2);
Machen wir einen Schritt zurĂŒck und ĂŒberprĂŒfen den folgenden Code:
int h = 127;
while (h--) {
_n[h] ^= 28;
_n[h] -= (_n[h] == 32 ? 32 : 0);
}
Anscheinend transformiert es das ursprĂŒngliche Array auf irgendeine Weise, so dass wir lesbare Zeilen erhalten können. Lassen Sie es uns separat ausfĂŒhren:
https://onlinegdb.com/SJNM9Og7v :
libX11.so
XOpenDisplay
XCreateSimpleWindow
XCreateImage
XPutImage
XMapWindow
XFlush
Um Funktionen aufzurufen, deren Format in einer Zeile so unterschiedlich ist, nutzt der Code die Tatsache aus, dass im C-Sprachstandard (void) keine Parameter und () eine beliebige Anzahl von Parametern bedeutet. Es bleibt nur, die resultierende Leere * in den entsprechenden ((long (*) ()) Typ und voila umzuwandeln:
w = ((long (*)()) dlsym(T, _n + (2 * 20))) (d, (*(long *)((char *) (*(long *)((char *) d + 232)) + 16))
Da wir wissen, was diese Konvertierungen bedeuten, können wir diese ungewöhnliche Verwendung von dlsym jetzt zuerst durch Zeichenfolgen ersetzen:
Nach dem Ersetzen der Zeilen:
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;
}
Und dann zu den nativen Funktionen:
Nach dem Ersetzen durch "native" Funktionen:
#include <X11/Xlib.h>
int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
int x_[616][1220];
extern long syscall(long, ...);
char m[19][20];
long w, N[2] = { 0, 1 << 29 };
int rn = 2166136261, _[8][40][64] = { 0 };
long R[2];
void *M, *d, *T;
void b(int t, int x, int y, int c, int l) {
if ((x >= 19 || y >= 19 || x < 0 || y < 0) || (m[y][x] == l)
|| (m[y][x] != c))
return;
m[y][x] = l;
b(t, x - 1, y, c, l);
b(t, x + 1, y, c, l);
b(t, x, y - 1, c, l);
b(t, x, y + 1, c, l);
}
void e(int t, int x, int y, int c, int l) {
if ((x >= 64 || y >= 40 || x < 0 || y < 0) || (_[t][y][x] == l)
|| (_[t][y][x] != c))
return;
_[t][y][x] = l;
e(t, x - 1, y, c, l);
e(t, x + 1, y, c, l);
e(t, x, y - 1, c, l);
e(t, x, y + 1, c, l);
}
void k(int t, int x, int y, int c, int l) {
while (c--) {
_[t][y][x++] = l;
_[t][y++][x++] = l;
}
}
void r(int t, int x, int y, int c, int l) {
while (c--) {
_[t][y][x--] = l;
_[t][y++][x--] = l;
}
}
void u(int t, int x, int y, int c, int l) {
while (c--)
_[t][y++][x] = l;
}
char *z[8] = {
(char[]) {4},
(char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
(char[]) {5, 1},
(char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
38 - 0,
4},
(char[]) {4}, (char[]) {4},
(char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
3, 30, 38 - 3, 4},
(char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
0, 8 + 0 + 0, 21, 12 - 0, 1,
31, 9 + 0, 12 - 0, 1,
55 - 0 - 0, 21, 12 - 0, 0,
32, 9 + 3, 12 - 3, 0,
8 + 3 + 3, 21, 12 - 3, 1,
31, 9 + 3, 12 - 3, 1,
55 - 3 - 3, 21, 12 - 3, 6,
14 + 0, 2, 31 + 0, 13, 4,
1 - 0, 31 + 0, 16, 7, 3,
30 + 3 * 0, 14, 6,
12 + 0 * 4, 3, 32 - 0,
11 + 0 * 8, 6, 14 + 1, 2,
31 + 1, 13, 4, 1 - 1,
31 + 1, 16, 7, 3,
30 + 3 * 1, 14, 6,
12 + 1 * 4, 3, 32 - 1,
11 + 1 * 8,
4}
};
void d_(int t, int p, int q) {
for (int y = 0; y < 40; y++)
for (int x = 0; x < 64; x++)
if (_[t]
[y][x])
x_[y + q * 16 + p * 16][x + 580 + p * 32 - q *
32] = _[t][y][x];
}
int main(int a, char *s[]) {
d = XOpenDisplay(0);
w = XCreateSimpleWindow(d, (*(long *) ((char *) (*(long *) ((char *)d + 232)) + 16)), 0, 0, 1220, 616, 1, 0, 0);
M = XCreateImage(d, (*(long *)((char *) (*(long *) ((char *)d + 232)) + 64)), (*(long *)((char *) (*(long *) ((char *)d + 232)) + 56)), 2, 0, (char *) x_, 1220, 616, 32, 0);
for (int i = 0; i < 8; i++) {
char *p = z[i];
int c = 0;
while (*p != 4) {
switch (*p) {
case 0:
k(i, p[1], p[2], p[3], c);
p += 4;
break;
case 1:
r(i, p[1], p[2], p[3], c);
p += 4;
break;
case 2:
u(i, p[1], p[2], p[3], c);
p += 4;
break;
case 3:
e(i, p[1]
, p[2], 0, c);
p += 3;
break;
case 5:
p = z[p[1]];
break;
case 6:
c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
p += 2;
break;
}
}
}
while (a++) {
int f = syscall(2, s[1], 0);
syscall(0, f, m, 380);
syscall(3, f);
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
if ((x % 14 == 2) && (y % 4 == 3))
m[y][x] = 46;
b(0, 2, 3, m[3][2], a & 1 ? 43 : 45);
b(0, 2, 7, m[7][2], a & 2 ? 43 : 45);
b(0, 2, 11, m[11][2], a & 4 ? 43 : 45);
b(0, 2, 15, m[15][2], a & 8 ? 43 : 45);
for (int i = 0; i < 20; i++)
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
if (m[y][x] == 62)
b(0, x + 1, y, m[y][x + 1],
!(m[y - 1][x] == 43 ? 1 : 0
|| m[y + 1][x] == 43 ? 1 : 0) ? 43 : 45);
for (int y = 0; y < 616; y++)
for (int x = 0; x < 1220; x++)
x_[y][x] = 0;
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
d_(((m[y][x] >> 4) & 1) << 2 | (m[y][x] & 3), x, y);
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
if ((x % 14 == 2) && (y % 4 == 3))
d_(7, x, y);
for (int y = 0; y < 616; y++)
for (int x = 0; x < 1220; x++) {
x_[y][x] &= 14737632 | (31 << ((x % 3) << 3));
x_[y][x] += 986895 & (rn *= 16777619);
}
XPutImage(d, w, (*(long *)((char *) (*(long *) ((char *)d + 232)) + 72)), M, 0, 0, 0, 0, 1220, 616);
XMapWindow(d, w);
XFlush(d);
syscall(35, &N, &R);
}
return 0;
}
Syscalls
Ersetzen wir die Systemaufrufe auf die gleiche Weise wie im ersten Teil:
Code ohne Systemaufrufe:
#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 und Offsets
Versuchen wir, die folgende Konstruktion zu zerlegen:
w = XCreateSimpleWindow(d, (*(long *) ((char *) (*(long *) ((char *)d + 232)) + 16)), 0, 0, 1220, 616, 1, 0, 0);
Eine Reihe von Typkonvertierungen, die auf den ersten Blick nur erforderlich sind, um den Leser zu verwirren, aber jede Konvertierung hat hier ihren eigenen Zweck, nÀmlich:
d ist ein Zeiger auf eine Anzeigestruktur im Xlib-Kontext. Es hat ein Array-Feld namens screen. Um einen Zeiger auf das erste Element dieses Arrays zu erhalten, mĂŒssen wir eine bestimmte Anzahl von Bytes (x64 - 232) ab dem Anzeigezeiger vorwĂ€rts zĂ€hlen. Da Display nicht char * ist, hĂ€tten wir beim direkten Lesen die GröĂe von (langen *) Bytes berechnet. Also setzen wir d in char * und verschieben 232 Bytes:
((char *)d + 232)
Wir haben die Position des ersten Screens-Elements im Speicher. Lassen Sie es uns in einen vollwertigen Zeiger konvertieren und dereferenzieren:
(*(long *) ((char *)d + 232))
Jetzt mĂŒssen wir innerhalb der Screens-Struktur einen Zeiger auf das Root-Fenster Root erhalten. Um dies zu tun, entfernen wir uns um 16 Bytes von Screens und dereferenzieren die Konstruktion:
(*(long *) ((char *) (*(long *) ((char *)d + 232)) + 16))
Dieses Konstrukt wird tatsÀchlich jeden Tag von Xlib-Programmierern verwendet, da es hÀufig verwendet wird
RootWindow(Display, DefaultScreen(Display))
In Ă€hnlicher Weise werden wir die entsprechenden Offsets an anderen Stellen ersetzen, um vertrautere Makros zu erhalten (gleichzeitig werden wir die EinrĂŒckungspfosten korrigieren):
Code nach dem Ersetzen von Offsets:
#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;
}
Bilddaten
Beachten Sie, dass XCreateImage einen Zeiger auf den Speicherbereich benötigt, in dem die Pixeldaten gespeichert werden. FĂŒr unseren Funktionsaufruf ist dies die Variable "x_". Benennen Sie es in pixdata um und suchen Sie alle Orte, an denen es verwendet wird:
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);
}
Isolieren wir den Block pixdata [..] = 0 in eine separate Funktion und versuchen herauszufinden, was das erste Auftreten bewirkt:
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];
Wenn Sie sich das wĂ€hrend des Programmiervorgangs erzeugte endgĂŒltige Bild genau ansehen, werden Sie leicht feststellen, dass 40 und 64 die GröĂe eines separaten âBlocksâ haben, aus dem die Schaltung aufgebaut ist.
Daher zeichnet diese Funktion eine separate "Kachel" auf die Leinwand des Hauptbilds, und nach der Indizierung des Arrays "_" ist die Variable "t" fĂŒr den Bildindex und p und q - fĂŒr die x- und y-Koordinaten verantwortlich. Benennen Sie auch "_" in Texturen um:
Der Code im 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;
}
Karte lesen
Lassen Sie uns die Zeilen open..close in eine separate Funktion trennen, in der der Inhalt der ausgewÀhlten Datei in die Variable m eingelesen wird (die wir in mapdata umbenennen).
Warum wird die Datei in jedem Zyklus gezĂ€hlt? Es war kĂŒrzer in Bezug auf Code und Token. Das "Rammen" des Codes dauerte ungefĂ€hr 4 Tage, um in die Grenzen der Regeln zu passen. Wenn Sie die Datei nur einmal lesen, sind zusĂ€tzlicher Speicher und ein Analogon der memcpy-Funktion erforderlich.
Spezielle Funktion _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;
}
Da wir die Mapdata-Variable berĂŒhrt haben, achten wir auf die Zeilen und Funktionen, in denen sie sich Ă€ndert. Dies ist die Funktion "b", die wir vorerst nicht berĂŒhren werden, und "main", in der wir unter BerĂŒcksichtigung des Inhalts der "vollstĂ€ndigen" Konfigurationsdateien Folgendes umgestalten:
Nach dem Refactoring von 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;
}
Um die Bearbeitung der Arbeit mit "mapdata" abzuschlieĂen, mĂŒssen Sie zwei weitere Fragen beantworten - was ist die Funktion "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);
}
Und was passiert im Block:
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);
Funktion "b"
Wenn Sie sich die Funktion "b" genau ansehen, werden Sie feststellen, dass sie der Implementierung des Flood_fill- Algorithmus , der mit seinem theoretischen Zweck ĂŒbereinstimmt, schmerzlich Ă€hnlich ist - er "ĂŒberflutet" den "Draht" mit dem gewĂŒnschten Zustand, sodass sich die aktuelle Wellenfront bis zum Ende des Drahtes ausbreiten kann. Benennen wir es um und platzieren es im Block "Produktion bereit".
Hochwasser fĂŒllen
#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;
}
Seltsamer Block
Jetzt bleibt zu analysieren, was in der Zeile passiert:
_texture_draw(((mapdata[y][x] >> 4) & 1) << 2 | (mapdata[y][x] & 3), x, y);
Da wir bereits eine vollstÀndige Tabelle mit ZustÀnden erstellt haben, die sich in den Map-Daten befinden können, können wir alle Ausgabewerte des ersten Parameters abrufen:
| AufzÀhlung | int | Ergebnis |
|---|---|---|
| MAPCHAR_WIRE | 46 | 2 |
| MAPCHAR_PLUS | 43 | 3 |
| MAPCHAR_MINUS | 45 | 1 |
| MAPCHAR_NOR | 62 | 6 |
| MAPCHAR_EMPTY | 32 | 0 |
Ja, das heiĂt, als Ergebnis dieser Transformation erhalten wir den Texturindex im Texturarray.
Es dauerte ein paar Stunden, um ĂŒber den Mechanismus der Erzeugung aus einem lesbaren und assoziativ verstĂ€ndlichen Satz von Symbolen in Texturindizes nachzudenken. Ich schrieb die Symbole aus, die DrĂ€hte und NOR-Elemente bedeuten könnten, und umkreiste dann, nachdem ich ihre BinĂ€rwerte gemalt hatte, die einzigartigen Bereiche. ZusĂ€tzlich zu der aktuellen gab es eine zweite Option mit komplexeren Berechnungen, die jedoch lĂ€nger ist und daher nicht dem Token-Limit entspricht.
GroĂartig, es gibt uns die Möglichkeit, eine andere Funktion zu isolieren und fĂŒr jede Textur eine AufzĂ€hlung zu deklarieren:
Nach einem weiteren 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;
}
Textur # 7
Wenn Sie sich das Array "z" genau ansehen, werden Sie feststellen, dass es 8 Datenblöcke als Konstante fĂŒr die Anzahl der Texturen enthĂ€lt. Und es hat sogar zwei Leerzeichen an den Positionen 4 und 5, genau wie in unserer AufzĂ€hlung, höchstwahrscheinlich handelt es sich um Texturdaten. Es enthĂ€lt jedoch 8 Bilder, und wir konnten nur 7 "öffnen". Wenn wir jedoch vorsichtig genug sind, können wir feststellen, dass es einen Code gibt, der speziell die 7. Textur zeichnet:
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);
An der Position können Sie bereits erraten, was es ist, aber lassen Sie uns diese Zeilen auskommentieren und die Anwendung ausfĂŒhren:
Vorher:
Nachher:
Jetzt wissen wir sicher, dass dies die Textur des Lochs auf dem Brett ist, und können es der AufzĂ€hlungsliste hinzufĂŒgen, indem wir es in einer separaten Funktion rendern:
Alle Texturen zusammengesetzt:
#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;
}
Shader
Die Katzen aus dem vorherigen Artikel versprachen Shader. Und sie sind hier. Und wo ist der Code, der fĂŒr die Verarbeitung verantwortlich ist?
_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(); //
Unter der Eliminierungsmethode verstehen wir, dass das Bildschirmrauschen und die Wirkung des LCD-Monitors diese beiden Linien ergeben. Wie arbeiten Sie?
Beginnen wir mit dem letzten:
pixdata[y][x] += 986895 & (rn *= 16777619);
Zu jedem Pixel wird der Wert 986895 hinzugefĂŒgt (der in hexadezimalen Versionen wie 0x0f0f0f aussieht), der zuvor mithilfe der Bit-UND-Operation in Kombination mit dem Ergebnis der Multiplikation von rn mit 16777619 durchgefĂŒhrt wurde. Wenn rn ein Zufallszahlengenerator wĂ€re, wĂŒrde dies ein körniges "Rauschen" erzeugen. auf dem Bildschirm innerhalb von 16 Abstufungen fĂŒr jeden Kanal. Und da das Rauschen auftritt, ist rn der Zufallszahlengenerator. Aber wie wird das erreicht?
int rn = 2166136261;
Zu Beginn des Programms wird die Variable rn mit der Nummer 2166136261 initialisiert. Bei jeder Iteration wird das Pixel mit 16777619 multipliziert. Dies ist nichts weiter als ein Pseudozufallszahlengenerator. Anstelle eines gut untersuchten Lineargenerators wird jedoch der FNV- Hashing-Algorithmus ohne XOR-Schritt verwendet, da wir das Endergebnis nicht benötigen.
Es bleibt abzuwarten, wie die vorherige Zeile funktioniert:
pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
Lassen Sie uns die Zahl 14737632 in ein hexadezimales Format konvertieren, da wir mit Ein-Byte-LichtkanĂ€len arbeiten: 0xe0e0e0. Und jetzt, wenn x gleich 0 bis 3 ist, fĂŒhren wir die entsprechenden Berechnungen durch:
0xe0e0e0 | (31 << ((0 % 3) << 3)) = e0e0ff
0xe0e0e0 | (31 << ((1 % 3) << 3)) = e0ffe0
0xe0e0e0 | (31 << ((2 % 3) << 3)) = ffe0e0
Wenn diese Masken nun mit der Operation "&" auf die Farbe des Pixels angewendet werden, erhalten wir jeweils stummgeschaltete R- und G-, R- und B-, G- und B-KanÀle, die wie der Effekt eines LCD-Monitors aussehen:
Lassen Sie uns sie in separate Funktionen unterteilen:
#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"
Es gibt noch 4 Funktionen, die wir nicht untersucht oder umbenannt haben - dies sind "e", "k", "r" und "u". Versuchen wir, sie zu inspizieren, ohne nach Orten zu suchen, von denen aus sie angerufen werden:
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);
}
Offensichtlich sieht diese Funktion wie Flut_FĂŒll aus und funktioniert nur fĂŒr das Texturen-Array. Benennen Sie es in _texture_fill um.
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;
}
}
Die Funktionen "k" und "r" fĂŒr jede gegebene Einheit c zeichnen zwei Pixel mit dem Wert l und bewegen sich um zwei Pixel nach rechts oder links und um eins nach unten - dies bedeutet, dass dies Funktionen zum Zeichnen der isometrischen Linien SW und SE sind. Benennen wir sie in _texture_linesw und _texture_linese um.
Zu diesem Zeitpunkt können Sie bereits erraten, dass die letzte Funktion "u" eine Linie vertikal nach unten zeichnet:
void u(int t, int x, int y, int c, int l) {
while (c--)
textures[t][y++][x] = l;
}
Benennen wir es in _texture_linedown um.
Alle Einzelfunktionen wurden ĂŒberarbeitet:
#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;
}
Vektorgrafiken
Es ist nur noch ein letzter Schritt ĂŒbrig - um herauszufinden, was im letzten Schaltkoffer passiert, der fĂŒr spĂ€ter ĂŒbrig bleibt:
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;
}
}
}
Jetzt, da die Funktionen neue, verstĂ€ndliche Namen haben, können wir sagen, dass dieser Codeblock Daten aus dem Array "z" interpretiert und gemÀà den darin enthaltenen Anweisungen (zum Beispiel 0, 5, 5, 8, 2 - "die Linie nach SĂŒden zieht). Ost, von [5,5] 8 Pixel lang auf der kurzen Seite mit der Farbnummer 2 ") zeichnet den gesamten Satz von Texturen.
Alles scheint klar zu sein, aber es wurde kein einziger Hinweis auf die Farbe im Programm bemerkt.
c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
Ja, das _x-Array ist also eine Palette, aber in einem sehr seltsamen, "komprimierten" Format.
int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
Da wir noch nicht wissen, wie viele Farben in der Palette verwendet werden (beim Festlegen der Farbe ist der Index mindestens durch 4 teilbar), formatieren wir die Datentabelle zum Zeichnen neu und gruppieren die Zahlen nach Kategorien, wobei die Befehlssignaturen durch Konstanten ersetzt werden:
Refactoring der Vektoranweisungstabelle
#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;
}
Die maximale Anzahl, die nach der Anweisung "TEXVEC_COLOR" steht, ist 16. Schreiben wir den einfachsten Code, um die gesamte Tabelle abzurufen :
Nachdem wir nun die entschlĂŒsselte Palette in unseren HĂ€nden haben, können wir die Funktion ihrer Verwendung ersetzen und gleichzeitig EntschlĂŒsselungen fĂŒr die Farben in die konstante Tabelle schreiben Markieren Sie die Funktion zum Erstellen von Texturen:
VollstÀndiger Code nach dem 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;
}
Epilog
Das ist alles.Trotz der Tatsache, dass ich keine Preise gewonnen habe, war es eine ziemlich merkwĂŒrdige Erfahrung (die Festplatte, die zwei Tage vor Beginn der Annahme der Arbeit starb, trug dazu bei). Es war etwas falsch daran, Code zu schreiben, der so unlesbar wie möglich und gleichzeitig aus sprachlicher Sicht absolut gĂŒltig war. Es kann jedoch nicht gesagt werden, dass es nicht interessant war. Wenn ein Dienstprogramm, das Token zĂ€hlt, angibt, dass der Code gegen die Regeln verstöĂt, indem er das Limit um mehr als 2000 Token ĂŒberschreitet, und Sie nicht wissen, wie Sie es verkĂŒrzen sollen, ist dies eine Herausforderung. Wenn die DateigröĂe die Grenzwerte ĂŒberschreitet und Sie einen Grafikeffekt hinzufĂŒgen möchten, ist dies eine Herausforderung. Es war schwierig, so viele Funktionen unterzubringen, und je sĂŒĂer es war, die Ausgabe des Dienstprogramms zu lesen, das nach mehreren hundert Korrekturen schlieĂlich besagte, dass der Code entladen werden konnte. Ich wĂŒrde den Lesern empfehlen, am Wettbewerb teilzunehmen, wenn auch nur zusich anzuschlieĂen und deine StĂ€rke zu testen.
Ja, es gibt keine Auszeichnungen oder Preise, aber Sie werden wissen, dass Sie sich auf der IOCCC-Website unter dem Spitznamen zhestokyshveller verstecken.