- How I participated in IOCCC-'19 (and lost). Part 1: "Tic-tac-toe"
- How I participated in IOCCC-'19 (and lost). Part 2: "NOR Simulator"
I hope this article will help you when parsing someone else's code or code after a decompiler or obfuscator.
If you still do not know what IOCCC is or you want to familiarize yourself with a simpler version of the obfuscated code, then I recommend turning to the first part.
To everyone else, I wish you pleasant reading.
All sources are placed on github , from where you can download them and try to compile them.
Initial data
Since the source code in text form can be found at the link, I will show how the code looks graphically:
Traditionally, "extra points" are given if the code is formatted non-standard or looks like some kind of image. Well, let's assume that this is all right here.
But what does the program do?
It initializes the X-server graphics stack, scans the provided configuration file, draws an electrical diagram according to the file and starts the simulation, alternately changing the polarity on the 4 input pins, using only NOR (Not-OR) elements. Rendering is done with the old LCD screen shader.
The program comes with several configuration files, namely:
DIP8-4packnot.txt - an approximate analogue of CMOS 4041 / Four-channel inverter
(The image is compressed in 2 times to fit the limits of decency. It's actually funny that the program, weighing 3.5 KB, generates a series of images that take up 10.5 + MB in maximum compression)
DIP8-triplexor.txt - an approximate analogue of CMOS 4030 with combined inputs and three channels / Three-channel XOR-gate with combined inputs
DIP8-fulladder.txt - an approximate analogue of CMOS 4008, but for two bits / adder for 2 bits with a carry bit output
Parsing the code
The most difficult task this time was to fit into the size limit of the submitted work. Not only the file size is limited, but also the number of conditional "tokens" - operation symbols, language keywords and parenthesis pairs. It is in order to "exploit" this feature of the size parser-checker in the program that a huge number of defines are declared, which reduce blocks of code to a single C keyword.
First, let's look into the Makefile to understand how the code is assembled:
#!/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}
As you can see, this work, just like the previous one, actively uses system calls to avoid ugly "#include" that break the pattern of the picture. Let's remember this fact and prepare a line for the preprocessor and linter:
After the preprocessor
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;
}
Well, we fulfilled at least one of the conditions of the competition, the code after the preprocessor did not become clearer.
Let's start with what you can catch at a glance and try to reconstruct the chain of events.
dlsym \ dlopen
Obviously, in order to use the functions of the X-server and create a window, and then draw something in it, the code must turn to the XLib library. The code contains dlopen / dlsym functions that allow you to dynamically load the library, but they are fed some tricky mess at the input:
char _n[] =
"pu~D--2os" "<<<<<<<<" "<<<DSlyrXuolp}e" "<<<<<<<<"
"D_ny}hyOuqlpyKurxsk<D_ny" "}hyUq}{y" "<<<<<<<<" "DLihUq}{y" "<<<<<<<<"
"<<<DQ}lKurxsk" "<<<<<<<<" "<<DZpiot<";
...
T = dlopen(_n, 2);
Let's take a step back and inspect the following code:
int h = 127;
while (h--) {
_n[h] ^= 28;
_n[h] -= (_n[h] == 32 ? 32 : 0);
}
Apparently, it transforms the original array in some way, allowing us to get readable lines. Let's execute it separately:
https://onlinegdb.com/SJNM9Og7v :
libX11.so
XOpenDisplay
XCreateSimpleWindow
XCreateImage
XPutImage
XMapWindow
XFlush
In order to call functions so different in format in one line, the code exploits the fact that in the C language standard (void) means no parameters, and () means any number of parameters. It remains only to cast the resulting void * to the corresponding ((long (*) ()) type and voila:
w = ((long (*)()) dlsym(T, _n + (2 * 20))) (d, (*(long *)((char *) (*(long *)((char *) d + 232)) + 16))
Knowing what these conversions mean, we can now replace this unusual use of dlsym first with strings:
After replacing the lines:
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;
}
And then to the native functions:
After replacing with `` native '' functions:
#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
Let's replace the system calls in the same way as we followed in the first part:
Code without system calls:
#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 and offsets
Let's try to disassemble the following construction:
w = XCreateSimpleWindow(d, (*(long *) ((char *) (*(long *) ((char *)d + 232)) + 16)), 0, 0, 1220, 616, 1, 0, 0);
A bunch of type conversions, which, at first glance, are only needed to confuse the reader, but each conversion here has its own purpose, namely:
d is a pointer to the Display structure in the Xlib context. It has an array field called screens and in order to get a pointer to the first element of this array, we must count a certain number of bytes (x64 - 232) from the Display pointer forward. Since Display is not char *, then with direct reading we would have calculated in sizeof (long *) bytes. So we cast d to char * and move 232 bytes:
((char *)d + 232)
We got the position of the first Screens element in memory. Let's convert it to a full-fledged pointer and dereference it:
(*(long *) ((char *)d + 232))
Now, inside the Screens structure, we need to get a pointer to the root window, Root. To do this, let's move away from Screens by 16 bytes and dereference the construction:
(*(long *) ((char *) (*(long *) ((char *)d + 232)) + 16))
This construct is actually used every day by Xlib programmers, since its commonly used equivalent is
RootWindow(Display, DefaultScreen(Display))
In a similar way, we will replace the corresponding offsets in other places in order to get more familiar macros (at the same time we will correct the indent jambs):
Code after replacing 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;
}
Image data
Note that XCreateImage requires a pointer to the memory area where the pixel data will be stored. For our function call, this is the "x_" variable. Rename it pixdata and find all the places where it is used:
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);
}
Let's isolate the pixdata [..] = 0 block into a separate function and try to figure out what the first occurrence does:
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];
If you look closely at the final image generated during the program operation, you will easily notice that 40 and 64 are the dimensions of a separate "block" from which the circuit is built.
Therefore, this function draws a separate "tile" on the canvas of the main image, and judging by the indexing of the "_" array, the "t" variable is responsible for the image index, and p and q - for the x and y coordinates. We'll also rename "_" to textures:
The code at the 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;
}
Reading the map
Let's separate the lines open..close into a separate function, where the contents of the selected file are read into the variable m (which we will rename to mapdata).
Why is the file counted in every cycle? It was shorter in terms of code and tokens. The process of "ramming" the code took about 4 days to fit into the limits of the rules. If you read the file only once, then additional storage and some analogue of the memcpy function would be required.
Dedicated function _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;
}
Since we have touched on the mapdata variable, let's pay attention to the lines and functions where it changes - this is the "b" function, which we will not touch for now and "main" where, paying attention to the contents of the "complete" configuration files, we will refactor:
After refactoring on 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;
}
In order to finish the processing of work with "mapdata", you need to answer two more questions - what is function "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);
}
And what happens in the 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);
Function "b"
If you look closely at function "b", you will notice that it is painfully similar to the implementation of the flood_fill algorithm , which coincides with its theoretical purpose - it "floods" the "wire" with the desired state, allowing the current wave front to propagate to the end of the wire. Let's rename it and place it in the "production ready" block.
Flood fill
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/* */
/*! \brief */
#define IMAGE_WIDTH (1220)
/*! \brief */
#define IMAGE_HEIGHT (616)
/*! \brief */
#define IMAGE_SHIFTX (580)
/*! \brief */
#define TEXTURE_COUNT (8)
/*! \brief */
#define TEXTURE_WIDTH (64)
/*! \brief */
#define TEXTURE_HEIGHT (40)
/*! \brief */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief */
#define TEXTURE_TOP_HEIGHT (32)
/*! \brief */
#define MAP_WIDTH (19)
/*! \brief */
#define MAP_HEIGHT (19)
/*! \brief -. '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief NOR- */
#define MAP_ITERATIONS (20)
/*! \brief - */
enum map_characters {
MAPCHAR_WIRE = '.', /**< (ASCII = 46) */
MAPCHAR_PLUS = '+', /**< ( ) (ASCII = 43) */
MAPCHAR_MINUS = '-', /**< ( ) (ASCII = 45) */
MAPCHAR_NOR = '>', /**< NOR- (ASCII = 62) */
};
/*! \brief .
* int */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief , */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief .
* '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];
/*! \brief Xlib */
Display * display;
/*! \brief Xlib */
Window window;
/*! \brief */
XImage * image;
/* \brief , */
static void _image_reset(void) {
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++)
pixdata[y][x] = 0;
}
/*! \brief
* \param[in] t
* \param[in] x X
* \param[in] y Y */
static void _texture_draw(int t, int x, int y) {
for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
if (textures[t][ty][tx])
pixdata[ty +
y * (TEXTURE_TOP_HEIGHT / 2) +
x * (TEXTURE_TOP_HEIGHT / 2)]
[tx +
IMAGE_SHIFTX +
x * (TEXTURE_TOP_WIDTH / 2) -
y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}
/*! \brief -
* \param[in] filename - */
static void _map_read(const char * filename) {
int f = open(filename, 0);
read(f, mapdata, MAP_FILEDATA);
close(f);
}
/*! \brief -
* */
static void _map_wire_inputs(void) {
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if ((x % 14 == 2) && (y % 4 == 3))
mapdata[y][x] = MAPCHAR_WIRE;
}
/*! \brief
* \param[in] t ,
* \param[in] x X-
* \param[in] y Y-
* \param[in] c
* \param[in] l */
static void _map_fill(int t, int x, int y, int c, int l) {
if ((x >= MAP_WIDTH || y >= MAP_HEIGHT ||
x < 0 || y < 0) || (mapdata[y][x] == l)
|| (mapdata[y][x] != c))
return;
mapdata[y][x] = l;
_map_fill(t, x - 1, y, c, l);
_map_fill(t, x + 1, y, c, l);
_map_fill(t, x, y - 1, c, l);
_map_fill(t, x, y + 1, c, l);
}
/*! \brief
* .
* \param[in] counter */
static void _map_wire_counter(int counter) {
_map_fill(0, 2, 3, mapdata[3][2], counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 7, mapdata[7][2], counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}
/*! \brief () NOR- */
static void _map_process_gates(void) {
for (int i = 0; i < MAP_ITERATIONS; i++)
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if (mapdata[y][x] == MAPCHAR_NOR)
_map_fill(0, x + 1, y, mapdata[y][x + 1],
!(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
|| mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ?
MAPCHAR_PLUS : MAPCHAR_MINUS);
}
/* */
int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
int rn = 2166136261;
void *T;
void e(int t, int x, int y, int c, int l) {
if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT ||
x < 0 || y < 0) ||
(textures[t][y][x] == l) ||
(textures[t][y][x] != c))
return;
textures[t][y][x] = l;
e(t, x - 1, y, c, l);
e(t, x + 1, y, c, l);
e(t, x, y - 1, c, l);
e(t, x, y + 1, c, l);
}
void k(int t, int x, int y, int c, int l) {
while (c--) {
textures[t][y][x++] = l;
textures[t][y++][x++] = l;
}
}
void r(int t, int x, int y, int c, int l) {
while (c--) {
textures[t][y][x--] = l;
textures[t][y++][x--] = l;
}
}
void u(int t, int x, int y, int c, int l) {
while (c--)
textures[t][y++][x] = l;
}
char *z[8] = {
(char[]) {4},
(char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
(char[]) {5, 1},
(char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
38 - 0,
4},
(char[]) {4},
(char[]) {4},
(char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
3, 30, 38 - 3, 4},
(char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
0, 8 + 0 + 0, 21, 12 - 0, 1,
31, 9 + 0, 12 - 0, 1,
55 - 0 - 0, 21, 12 - 0, 0,
32, 9 + 3, 12 - 3, 0,
8 + 3 + 3, 21, 12 - 3, 1,
31, 9 + 3, 12 - 3, 1,
55 - 3 - 3, 21, 12 - 3, 6,
14 + 0, 2, 31 + 0, 13, 4,
1 - 0, 31 + 0, 16, 7, 3,
30 + 3 * 0, 14, 6,
12 + 0 * 4, 3, 32 - 0,
11 + 0 * 8, 6, 14 + 1, 2,
31 + 1, 13, 4, 1 - 1,
31 + 1, 16, 7, 3,
30 + 3 * 1, 14, 6,
12 + 1 * 4, 3, 32 - 1,
11 + 1 * 8,
4}
};
int main(int a, char *s[]) {
display = XOpenDisplay(0);
window = XCreateSimpleWindow(display,
RootWindow(display, DefaultScreen(display)),
0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
image = XCreateImage(display,
DefaultVisual(display, DefaultScreen(display)),
DefaultDepth(display, DefaultScreen(display)),
2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
for (int i = 0; i < 8; i++) {
char *p = z[i];
int c = 0;
while (*p != 4) {
switch (*p) {
case 0:
k(i, p[1], p[2], p[3], c);
p += 4;
break;
case 1:
r(i, p[1], p[2], p[3], c);
p += 4;
break;
case 2:
u(i, p[1], p[2], p[3], c);
p += 4;
break;
case 3:
e(i, p[1]
, p[2], 0, c);
p += 3;
break;
case 5:
p = z[p[1]];
break;
case 6:
c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
p += 2;
break;
}
}
}
while (a++) {
_map_read(s[1]);
_map_wire_inputs();
_map_wire_counter(a);
_map_process_gates();
_image_reset();
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
_texture_draw(((mapdata[y][x] >> 4) & 1) << 2 | (mapdata[y][x] & 3), x, y);
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if ((x % 14 == 2) && (y % 4 == 3))
_texture_draw(7, x, y);
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++) {
pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
pixdata[y][x] += 986895 & (rn *= 16777619);
}
XPutImage(display, window,
DefaultGC(display, DefaultScreen(display)),
image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
XMapWindow(display, window);
XFlush(display);
sleep(1);
}
return 0;
}
Strange block
Now it remains to parse what is happening in the line:
_texture_draw(((mapdata[y][x] >> 4) & 1) << 2 | (mapdata[y][x] & 3), x, y);
Since we have already built a complete table of states that can be inside the mapdata, we can get all the output values of the first parameter:
enum | int | Result |
---|---|---|
MAPCHAR_WIRE | 46 | 2 |
MAPCHAR_PLUS | 43 | 3 |
MAPCHAR_MINUS | 45 | 1 |
MAPCHAR_NOR | 62 | 6 |
MAPCHAR_EMPTY | 32 | 0 |
Yeah, that is, as a result of this transformation, we get the texture index in the texture array.
It took a couple of hours to think over the mechanism of generation from a readable and associatively understandable set of symbols into texture indexes. I wrote out the symbols that could mean wires and NOR elements and then, having painted their binary values, I circled the unique areas. In addition to the current one, there was a second option with more complex calculations, but it is longer, therefore, it did not fit the token limit.
Great, it gives us the ability to isolate another function and declare an enum for each texture:
After another refactoring:
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/* */
/*! \brief */
#define IMAGE_WIDTH (1220)
/*! \brief */
#define IMAGE_HEIGHT (616)
/*! \brief */
#define IMAGE_SHIFTX (580)
/*! \brief */
#define TEXTURE_COUNT (8)
/*! \brief */
#define TEXTURE_WIDTH (64)
/*! \brief */
#define TEXTURE_HEIGHT (40)
/*! \brief */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief */
#define TEXTURE_TOP_HEIGHT (32)
/*! \brief */
#define MAP_WIDTH (19)
/*! \brief */
#define MAP_HEIGHT (19)
/*! \brief -. '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief NOR- */
#define MAP_ITERATIONS (20)
/*! \brief - */
enum map_characters {
MAPCHAR_WIRE = '.', /**< (ASCII = 46) */
MAPCHAR_PLUS = '+', /**< ( ) (ASCII = 43) */
MAPCHAR_MINUS = '-', /**< ( ) (ASCII = 45) */
MAPCHAR_NOR = '>', /**< NOR- (ASCII = 62) */
MAPCHAR_EMPTY = ' ', /**< (ASCII = 32) */
};
/*! \brief */
enum textures_indexes {
TEXINDEX_EMPTY = (0), /**< */
TEXINDEX_MINUS = (1), /**< " " */
TEXINDEX_WIRE = (2), /**< */
TEXINDEX_PLUS = (3), /**< "" */
/**/
TEXINDEX_NOR = (6) /**< NOR- */
};
/*! \brief */
enum program_arguments {
ARG_PROGRAM, /**< */
ARG_BLUEPRINT /**< - */
};
/*! \brief .
* int */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief , */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief .
* '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];
/*! \brief Xlib */
Display * display;
/*! \brief Xlib */
Window window;
/*! \brief */
XImage * image;
/* \brief , */
static void _image_reset(void) {
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++)
pixdata[y][x] = 0;
}
/*! \brief
* \param[in] elem
* \return */
static int _map2texture(char elem) {
return ((elem >> 4) & 1) << 2 | (elem & 3);
}
/*! \brief */
static void _image_compile(void) {
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
_texture_draw(_map2texture(mapdata[y][x]), x, y);
}
/*! \brief */
static void _image_draw(void) {
XPutImage(display, window,
DefaultGC(display, DefaultScreen(display)),
image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
XMapWindow(display, window);
XFlush(display);
}
/*! \brief
* \param[in] t
* \param[in] x X
* \param[in] y Y */
static void _texture_draw(int t, int x, int y) {
for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
if (textures[t][ty][tx])
pixdata[ty +
y * (TEXTURE_TOP_HEIGHT / 2) +
x * (TEXTURE_TOP_HEIGHT / 2)]
[tx +
IMAGE_SHIFTX +
x * (TEXTURE_TOP_WIDTH / 2) -
y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}
/*! \brief -
* \param[in] filename - */
static void _map_read(const char * filename) {
int f = open(filename, 0);
read(f, mapdata, MAP_FILEDATA);
close(f);
}
/*! \brief -
* */
static void _map_wire_inputs(void) {
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if ((x % 14 == 2) && (y % 4 == 3))
mapdata[y][x] = MAPCHAR_WIRE;
}
/*! \brief
* \param[in] t ,
* \param[in] x X-
* \param[in] y Y-
* \param[in] c
* \param[in] l */
static void _map_fill(int t, int x, int y, int c, int l) {
if ((x >= MAP_WIDTH || y >= MAP_HEIGHT ||
x < 0 || y < 0) || (mapdata[y][x] == l)
|| (mapdata[y][x] != c))
return;
mapdata[y][x] = l;
_map_fill(t, x - 1, y, c, l);
_map_fill(t, x + 1, y, c, l);
_map_fill(t, x, y - 1, c, l);
_map_fill(t, x, y + 1, c, l);
}
/*! \brief
* .
* \param[in] counter */
static void _map_wire_counter(int counter) {
_map_fill(0, 2, 3, mapdata[3][2], counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 7, mapdata[7][2], counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}
/*! \brief () NOR- */
static void _map_process_gates(void) {
for (int i = 0; i < MAP_ITERATIONS; i++)
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if (mapdata[y][x] == MAPCHAR_NOR)
_map_fill(0, x + 1, y, mapdata[y][x + 1],
!(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
|| mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ?
MAPCHAR_PLUS : MAPCHAR_MINUS);
}
/* */
int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
int rn = 2166136261;
void *T;
void e(int t, int x, int y, int c, int l) {
if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT ||
x < 0 || y < 0) ||
(textures[t][y][x] == l) ||
(textures[t][y][x] != c))
return;
textures[t][y][x] = l;
e(t, x - 1, y, c, l);
e(t, x + 1, y, c, l);
e(t, x, y - 1, c, l);
e(t, x, y + 1, c, l);
}
void k(int t, int x, int y, int c, int l) {
while (c--) {
textures[t][y][x++] = l;
textures[t][y++][x++] = l;
}
}
void r(int t, int x, int y, int c, int l) {
while (c--) {
textures[t][y][x--] = l;
textures[t][y++][x--] = l;
}
}
void u(int t, int x, int y, int c, int l) {
while (c--)
textures[t][y++][x] = l;
}
char *z[8] = {
(char[]) {4},
(char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
(char[]) {5, 1},
(char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
38 - 0,
4},
(char[]) {4},
(char[]) {4},
(char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
3, 30, 38 - 3, 4},
(char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
0, 8 + 0 + 0, 21, 12 - 0, 1,
31, 9 + 0, 12 - 0, 1,
55 - 0 - 0, 21, 12 - 0, 0,
32, 9 + 3, 12 - 3, 0,
8 + 3 + 3, 21, 12 - 3, 1,
31, 9 + 3, 12 - 3, 1,
55 - 3 - 3, 21, 12 - 3, 6,
14 + 0, 2, 31 + 0, 13, 4,
1 - 0, 31 + 0, 16, 7, 3,
30 + 3 * 0, 14, 6,
12 + 0 * 4, 3, 32 - 0,
11 + 0 * 8, 6, 14 + 1, 2,
31 + 1, 13, 4, 1 - 1,
31 + 1, 16, 7, 3,
30 + 3 * 1, 14, 6,
12 + 1 * 4, 3, 32 - 1,
11 + 1 * 8,
4}
};
int main(int argc, char * args[]) {
display = XOpenDisplay(0);
window = XCreateSimpleWindow(display,
RootWindow(display, DefaultScreen(display)),
0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
image = XCreateImage(display,
DefaultVisual(display, DefaultScreen(display)),
DefaultDepth(display, DefaultScreen(display)),
2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
for (int i = 0; i < 8; i++) {
char *p = z[i];
int c = 0;
while (*p != 4) {
switch (*p) {
case 0:
k(i, p[1], p[2], p[3], c);
p += 4;
break;
case 1:
r(i, p[1], p[2], p[3], c);
p += 4;
break;
case 2:
u(i, p[1], p[2], p[3], c);
p += 4;
break;
case 3:
e(i, p[1]
, p[2], 0, c);
p += 3;
break;
case 5:
p = z[p[1]];
break;
case 6:
c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
p += 2;
break;
}
}
}
unsigned int counter = 0;
while (counter++) {
_map_read(args[ARG_BLUEPRINT]);
_map_wire_inputs();
_map_wire_counter(counter);
_map_process_gates();
_image_reset();
_image_compile();
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if ((x % 14 == 2) && (y % 4 == 3))
_texture_draw(7, x, y);
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++) {
pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
pixdata[y][x] += 986895 & (rn *= 16777619);
}
_image_draw();
sleep(1);
}
return 0;
}
Texture # 7
If you look closely at the "z" array, you will notice that it contains 8 data blocks as a constant for the number of textures. And it even has two spaces at positions 4 and 5, just like in our enum, most likely this is texture data. However, it contains 8 images, and we were able to "open" only 7. However, if we are careful enough, we can notice that there is a piece of code that draws specifically the 7th texture:
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if ((x % 14 == 2) && (y % 4 == 3))
_texture_draw(7, x, y);
By the position, you can already guess what it is, but comment out these lines and run the application:
Before:
After:
Now we know for sure that this is the texture of the hole on the board and we can add it to the enum list by rendering it in a separate function:
All textures assembled:
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/* */
/*! \brief */
#define IMAGE_WIDTH (1220)
/*! \brief */
#define IMAGE_HEIGHT (616)
/*! \brief */
#define IMAGE_SHIFTX (580)
/*! \brief */
#define TEXTURE_COUNT (8)
/*! \brief */
#define TEXTURE_WIDTH (64)
/*! \brief */
#define TEXTURE_HEIGHT (40)
/*! \brief */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief */
#define TEXTURE_TOP_HEIGHT (32)
/*! \brief */
#define MAP_WIDTH (19)
/*! \brief */
#define MAP_HEIGHT (19)
/*! \brief -. '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief NOR- */
#define MAP_ITERATIONS (20)
/*! \brief - */
enum map_characters {
MAPCHAR_WIRE = '.', /**< (ASCII = 46) */
MAPCHAR_PLUS = '+', /**< ( ) (ASCII = 43) */
MAPCHAR_MINUS = '-', /**< ( ) (ASCII = 45) */
MAPCHAR_NOR = '>', /**< NOR- (ASCII = 62) */
MAPCHAR_EMPTY = ' ', /**< (ASCII = 32) */
};
/*! \brief */
enum textures_indexes {
TEXINDEX_EMPTY = (0), /**< */
TEXINDEX_MINUS = (1), /**< " " */
TEXINDEX_WIRE = (2), /**< */
TEXINDEX_PLUS = (3), /**< "" */
/**/
TEXINDEX_NOR = (6), /**< NOR- */
TEXINDEX_HOLE = (7) /**< */
};
/*! \brief */
enum program_arguments {
ARG_PROGRAM, /**< */
ARG_BLUEPRINT /**< - */
};
/*! \brief .
* int */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief , */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief .
* '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];
/*! \brief Xlib */
Display * display;
/*! \brief Xlib */
Window window;
/*! \brief */
XImage * image;
static void _texture_draw(int t, int x, int y);
/*! \brief */
static void _image_create(void) {
display = XOpenDisplay(0);
window = XCreateSimpleWindow(display,
RootWindow(display, DefaultScreen(display)),
0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
image = XCreateImage(display,
DefaultVisual(display, DefaultScreen(display)),
DefaultDepth(display, DefaultScreen(display)),
2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
}
/* \brief , */
static void _image_reset(void) {
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++)
pixdata[y][x] = 0;
}
/*! \brief
* \param[in] elem
* \return */
static int _map2texture(char elem) {
return ((elem >> 4) & 1) << 2 | (elem & 3);
}
/*! \brief */
static void _image_compile(void) {
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
_texture_draw(_map2texture(mapdata[y][x]), x, y);
}
/*! \brief */
static void _image_draw(void) {
XPutImage(display, window,
DefaultGC(display, DefaultScreen(display)),
image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
XMapWindow(display, window);
XFlush(display);
}
/*! \brief */
static void _image_drill(void) {
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if ((x % 14 == 2) && (y % 4 == 3))
_texture_draw(TEXINDEX_HOLE, x, y);
}
/*! \brief
* \param[in] t
* \param[in] x X
* \param[in] y Y */
static void _texture_draw(int t, int x, int y) {
for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
if (textures[t][ty][tx])
pixdata[ty +
y * (TEXTURE_TOP_HEIGHT / 2) +
x * (TEXTURE_TOP_HEIGHT / 2)]
[tx +
IMAGE_SHIFTX +
x * (TEXTURE_TOP_WIDTH / 2) -
y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}
/*! \brief -
* \param[in] filename - */
static void _map_read(const char * filename) {
int f = open(filename, 0);
read(f, mapdata, MAP_FILEDATA);
close(f);
}
/*! \brief -
* */
static void _map_wire_inputs(void) {
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if ((x % 14 == 2) && (y % 4 == 3))
mapdata[y][x] = MAPCHAR_WIRE;
}
/*! \brief
* \param[in] t ,
* \param[in] x X-
* \param[in] y Y-
* \param[in] c
* \param[in] l */
static void _map_fill(int t, int x, int y, int c, int l) {
if ((x >= MAP_WIDTH || y >= MAP_HEIGHT ||
x < 0 || y < 0) || (mapdata[y][x] == l)
|| (mapdata[y][x] != c))
return;
mapdata[y][x] = l;
_map_fill(t, x - 1, y, c, l);
_map_fill(t, x + 1, y, c, l);
_map_fill(t, x, y - 1, c, l);
_map_fill(t, x, y + 1, c, l);
}
/*! \brief
* .
* \param[in] counter */
static void _map_wire_counter(int counter) {
_map_fill(0, 2, 3, mapdata[3][2], counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 7, mapdata[7][2], counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}
/*! \brief () NOR- */
static void _map_process_gates(void) {
for (int i = 0; i < MAP_ITERATIONS; i++)
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if (mapdata[y][x] == MAPCHAR_NOR)
_map_fill(0, x + 1, y, mapdata[y][x + 1],
!(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
|| mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ?
MAPCHAR_PLUS : MAPCHAR_MINUS);
}
/* */
int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
int rn = 2166136261;
void *T;
void e(int t, int x, int y, int c, int l) {
if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT ||
x < 0 || y < 0) ||
(textures[t][y][x] == l) ||
(textures[t][y][x] != c))
return;
textures[t][y][x] = l;
e(t, x - 1, y, c, l);
e(t, x + 1, y, c, l);
e(t, x, y - 1, c, l);
e(t, x, y + 1, c, l);
}
void k(int t, int x, int y, int c, int l) {
while (c--) {
textures[t][y][x++] = l;
textures[t][y++][x++] = l;
}
}
void r(int t, int x, int y, int c, int l) {
while (c--) {
textures[t][y][x--] = l;
textures[t][y++][x--] = l;
}
}
void u(int t, int x, int y, int c, int l) {
while (c--)
textures[t][y++][x] = l;
}
char *z[8] = {
(char[]) {4},
(char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
(char[]) {5, 1},
(char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
38 - 0,
4},
(char[]) {4},
(char[]) {4},
(char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
3, 30, 38 - 3, 4},
(char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
0, 8 + 0 + 0, 21, 12 - 0, 1,
31, 9 + 0, 12 - 0, 1,
55 - 0 - 0, 21, 12 - 0, 0,
32, 9 + 3, 12 - 3, 0,
8 + 3 + 3, 21, 12 - 3, 1,
31, 9 + 3, 12 - 3, 1,
55 - 3 - 3, 21, 12 - 3, 6,
14 + 0, 2, 31 + 0, 13, 4,
1 - 0, 31 + 0, 16, 7, 3,
30 + 3 * 0, 14, 6,
12 + 0 * 4, 3, 32 - 0,
11 + 0 * 8, 6, 14 + 1, 2,
31 + 1, 13, 4, 1 - 1,
31 + 1, 16, 7, 3,
30 + 3 * 1, 14, 6,
12 + 1 * 4, 3, 32 - 1,
11 + 1 * 8,
4}
};
int main(int argc, char * args[]) {
_image_create();
for (int i = 0; i < 8; i++) {
char *p = z[i];
int c = 0;
while (*p != 4) {
switch (*p) {
case 0:
k(i, p[1], p[2], p[3], c);
p += 4;
break;
case 1:
r(i, p[1], p[2], p[3], c);
p += 4;
break;
case 2:
u(i, p[1], p[2], p[3], c);
p += 4;
break;
case 3:
e(i, p[1]
, p[2], 0, c);
p += 3;
break;
case 5:
p = z[p[1]];
break;
case 6:
c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
p += 2;
break;
}
}
}
unsigned int counter = 1;
while (counter++) {
_map_read(args[ARG_BLUEPRINT]);
_map_wire_inputs();
_map_wire_counter(counter);
_map_process_gates();
_image_reset();
_image_compile();
_image_drill();
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++) {
pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
pixdata[y][x] += 986895 & (rn *= 16777619);
}
_image_draw();
sleep(1);
}
return 0;
}
Shaders
The cats from the previous article promised shaders. And they are here. And where is the code that is responsible for processing them?
_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(); //
By the method of elimination, we understand that the screen noise and the effect of the LCD monitor give these two lines. How do they work?
Let's start with the last one:
pixdata[y][x] += 986895 & (rn *= 16777619);
To each pixel is added the value 986895 (which in hex versions looks like 0x0f0f0f), which was previously by means of the bit-AND operation combined with the result of multiplying rn by 16777619. If rn were a random number generator, it would create a grainy "noise" on the screen within 16 gradations for each channel. And since the noise appears, then rn is the random number generator. But how is this achieved?
int rn = 2166136261;
At the very beginning of the program, the rn variable is initialized with the number 2166136261. And at each iteration, the pixel is multiplied by 16777619. This is nothing more than a pseudo-random number generator. But instead of a well-studied linear generator, the FNV hashing algorithm is used without an XOR step, since we do not need the final result.
It remains to be seen how the previous line works:
pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
Let's convert the number 14737632 into hexadecimal format, since we are working with one-byte light channels: 0xe0e0e0. And now, taking x equal from 0 to 3, we carry out the corresponding calculations:
0xe0e0e0 | (31 << ((0 % 3) << 3)) = e0e0ff
0xe0e0e0 | (31 << ((1 % 3) << 3)) = e0ffe0
0xe0e0e0 | (31 << ((2 % 3) << 3)) = ffe0e0
If we now apply these masks using the "&" operation to the color of a pixel, we will get, respectively, muted R and G, R and B, G and B channels, which will look like the effect of an LCD monitor:
Let's separate them into separate functions:
#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"
There are still 4 functions that we have not researched or renamed - these are "e", "k", "r" and "u". Let's try to inspect them without looking for places where they are called from:
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);
}
Obviously this function looks and works like flood_fill, only for the textures array, rename it to _texture_fill.
void k(int t, int x, int y, int c, int l) {
while (c--) {
textures[t][y][x++] = l;
textures[t][y++][x++] = l;
}
}
void r(int t, int x, int y, int c, int l) {
while (c--) {
textures[t][y][x--] = l;
textures[t][y++][x--] = l;
}
}
Functions "k" and "r" for each given unit c draw two pixels with the value of l and move to the right or left by two pixels and down by one - this means that these are functions for drawing isometric lines SW and SE. Let's rename them to _texture_linesw and _texture_linese.
At this point, you can already guess that the last function "u" draws a line vertically downward:
void u(int t, int x, int y, int c, int l) {
while (c--)
textures[t][y++][x] = l;
}
Let's rename it to _texture_linedown.
All individual functions have been refactored:
#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;
}
Vector graphics
The last step remains - to figure out what is going on in the last switch-case, left for later:
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;
}
}
}
Now that the functions have new, understandable names, we can say that this block of code interprets data from the array "z", and according to the instructions contained in it (for example, 0, 5, 5, 8, 2 - "draw the line South- East, from [5,5] 8 pixels long on the short side with color number 2 ") draws the entire set of textures.
Everything seems to be clear, but not a single indication of the color in the program was noticed.
c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
Yeah, so the _x array is a palette, but in a very strange, "compressed" format.
int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
Since we do not yet know how many colors are used in the palette (when setting the color, the index is at least divisible by 4), we reformat the data table for drawing and group the numbers by categories, replacing the instruction signatures with constants:
Refactoring the vector instruction table
#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;
}
The maximum number that stands after the "TEXVEC_COLOR" instruction is 16. Let's write the simplest code to get the entire table:
Now, having the decrypted palette in our hands, we can replace the function of its use and write decryptions for the colors in the constant table, and at the same time highlight the function of creating textures:
Complete code after 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;
}
Epilogue
That's all.Despite the fact that I did not win any prizes, it was a rather curious experience (the HDD who died two days before the start of accepting the work contributed to this). There was something wrong in writing code that was as unreadable as possible and at the same time absolutely valid from the point of view of the language. However, it cannot be said that it was not interesting. When a utility that counts tokens says that the code breaks the rules by exceeding the limit by 2000+ tokens, and you don't know how to shorten it, that's a challenge. When the file size exceeds the limits, and you want to add some kind of graphic effect, this is a challenge. It was difficult, to accommodate so much functionality, and the sweeter it was to read the output of the utility, which, after several hundred corrections, finally said that the code could be unloaded. I would recommend readers to participate in the competition, if only just toto join and test your strength.
Yes, it does not give any awards or prizes, but you will know that you are hiding under the nickname zhestokyshveller on the IOCCC website.