この記事が、デコンパイラーまたは難読化ツールの後で他の人のコードまたはコードを解析するときに役立つことを願っています。
それでもIOCCCが何であるかわからない場合、または難読化されたコードのより単純なバージョンに慣れたい場合は、最初の部分に目を向けることをお勧めします。
皆様、どうぞよろしくお願いいたします。
すべてのソースはgithubに配置されており、そこからダウンロードしてコンパイルを試みることができます。
初期データ
テキスト形式のソースコードはここにあるので、コードがどのようにグラフィカルに表示されるかを示します。
従来、コードが非標準でフォーマットされているか、ある種の画像のように見える場合、「余分なポイント」が与えられるようになりました。さて、これで大丈夫だとしましょう。
しかし、プログラムは何をしますか?
Xサーバーグラフィックスタックを初期化し、提供された構成ファイルをスキャンし、ファイルに従って電気図を描画してシミュレーションを開始し、NOR(Not-OR)要素のみを使用して4つの入力ピンの極性を交互に変更します。レンダリングは古いLCDスクリーンシェーダーで行われます。
プログラムには、次のようないくつかの構成ファイルが付属しています。
DIP8-4packnot.txt-CMOS 4041/4チャンネルインバーターのおおよそのアナログ
(画像は品位の限界に合うように2倍に圧縮されます。3.5KBのプログラムが最大圧縮で10.5 + MBを占める一連の画像を生成するのは実際には面白いです)
DIP8-triplexor.txt-入力と3つのチャネルを組み合わせたCMOS4030のおおよそのアナログ/ 3チャネルのXOR-入力を組み合わせたゲート
DIP8-fulladder.txt-CMOS 4008の近似アナログですが、2ビット用/キャリービット出力付きの2ビット用の加算器
コードの解析
今回の最も難しかったのは、提出された作品のサイズ制限に合わせるということでした。ファイルサイズが制限されるだけでなく、条件付き「トークン」の数(操作記号、言語キーワード、括弧のペア)も制限されます。プログラムでサイズパーサーチェッカーのこの機能を「活用」するために、膨大な数の定義が宣言され、コードのブロックが1つのCキーワードに削減されます。
まず、Makefileを調べて、コードがどのように組み立てられるかを理解しましょう。
#!/usr/bin/env make
PROJECT=prog
CC= gcc
SRC=prog.c
CWARN=-Wall -Wextra -Wno-char-subscripts
CSTD= -std=c99
# Syscalls table
# DS - syscall nanosleep
# DO - syscall open
# DR - syscall read
# DC - syscall close
# X11 structures offsets
# dS - offset of screens in Display
# dR - offset of root in Screen
# dD - offset of root_depth in Screen
# dV - offset of root_visual in Screen
# dG - offset of default_gc in Screen
BITS := $(shell uname -p)
ifeq ($(BITS), x86_64)
ARCH= -m64
CDEFINE= -DDS=35 -DDO=2 -DDR=0 -DDC=3 -DdS=232 -DdR=16 -DdD=56 -DdV=64 -DdG=72
else
ARCH= -m32
CDEFINE= -DDS=162 -DDO=5 -DDR=3 -DDC=6 -DdS=140 -DdR=8 -DdD=36 -DdV=40 -DdG=44
endif
OPT= -g
CFLAGS= ${CWARN} ${CSTD} ${ARCH} ${CDEFINE} ${OPT}
LDFLAGS= -ldl
RM= rm
all: ${PROJECT}
${PROJECT}:
${CC} ${CFLAGS} ${SRC} -o $@ ${LDFLAGS}
clean:
${RM} -f ${PROJECT}
ご覧のとおり、この作業は前の作業と同様に、システム呼び出しを積極的に使用して、画像のパターンを壊す醜い「#include」を回避します。この事実を覚えて、プリプロセッサとリンターの行を準備しましょう。
プリプロセッサの後
gcc -DDS=35 -DDO=2 -DDR=0 -DDC=3 -DdS=232 -DdR=16 -DdD=56 -DdV=64 -DdG=72 prog.c -ldl -E | indent -kr -brf > /tmp/fmt.c
int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
extern void *dlsym(void *, char *);
int x_[616][1220];
extern long syscall(long, ...);
extern void *dlopen(char *, int);
char m[19][20], _n[] =
"pu~D--2os" "<<<<<<<<" "<<<DSlyrXuolp}e" "<<<<<<<<"
"D_ny}hyOuqlpyKurxsk<D_ny" "}hyUq}{y" "<<<<<<<<" "DLihUq}{y" "<<<<<<<<"
"<<<DQ}lKurxsk" "<<<<<<<<" "<<DZpiot<";
long w, N[2] = { 0, 1 << 29 };
int rn = 2166136261, _[8][40][64] = { 0 };
long R[2];
void *M, *d, *T;
void b(int t, int x, int y, int c, int l) {
if ((x >= 19 || y >= 19 || x < 0 || y < 0) || (m[y][x] == l)
|| (m[y][x] != c))
return;
m[y][x] = l;
b(t, x - 1, y, c, l);
b(t, x + 1, y, c, l);
b(t, x, y - 1, c, l);
b(t, x, y + 1, c, l);
}
void e(int t, int x, int y, int c, int l) {
if ((x >= 64 || y >= 40 || x < 0 || y < 0) || (_[t][y][x] == l)
|| (_[t][y][x] != c))
return;
_[t][y][x] = l;
e(t, x - 1, y, c, l);
e(t, x + 1, y, c, l);
e(t, x, y - 1, c, l);
e(t, x, y + 1, c, l);
}
void k(int t, int x, int y, int c, int l) {
while (c--) {
_[t][y][x++] = l;
_[t][y++][x++] = l;
}
}
void r(int t, int x, int y, int c, int l) {
while (c--) {
_[t][y][x--] = l;
_[t][y++][x--] = l;
}
}
void u(int t, int x, int y, int c, int l) {
while (c--)
_[t][y++][x] = l;
}
char *z[8] = {
(char[]) {4},
(char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
(char[]) {5, 1},
(char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
38 - 0,
4},
(char[]) {4}, (char[]) {4},
(char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
3, 30, 38 - 3, 4},
(char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
0, 8 + 0 + 0, 21, 12 - 0, 1,
31, 9 + 0, 12 - 0, 1,
55 - 0 - 0, 21, 12 - 0, 0,
32, 9 + 3, 12 - 3, 0,
8 + 3 + 3, 21, 12 - 3, 1,
31, 9 + 3, 12 - 3, 1,
55 - 3 - 3, 21, 12 - 3, 6,
14 + 0, 2, 31 + 0, 13, 4,
1 - 0, 31 + 0, 16, 7, 3,
30 + 3 * 0, 14, 6,
12 + 0 * 4, 3, 32 - 0,
11 + 0 * 8, 6, 14 + 1, 2,
31 + 1, 13, 4, 1 - 1,
31 + 1, 16, 7, 3,
30 + 3 * 1, 14, 6,
12 + 1 * 4, 3, 32 - 1,
11 + 1 * 8,
4}
};
void d_(int t, int p, int q) {
for (int y = 0; y < 40; y++)
for (int x = 0; x < 64; x++)
if (_[t]
[y][x])
x_[y + q * 16 + p * 16][x + 580 + p * 32 - q *
32] = _[t][y][x];
}
int main(int a, char *s[]) {
int h = 127;
while (h--) {
_n[h] ^= 28;
_n[h] -= (_n[h] == 32 ? 32 : 0);
}
T = dlopen(_n, 2);
d = ((void *(*)()) dlsym(T, _n + (1 * 20))) (0);
w = ((long (*)()) dlsym(T, _n + (2 * 20))) (d,
(*(long *)
((char
*) (*(long *) ((char *)
d +
232)) +
16))
, 0, 0, 1220, 616, 1, 0,
0);
M = ((void *(*)()) dlsym(T, _n + (3 * 20))) (d,
(*(long *)
((char
*) (*(long *) ((char *)
d +
232)) +
64)),
(*(long *)
((char
*) (*(long *) ((char *)
d +
232)) +
56)), 2, 0, (char *) x_,
1220, 616, 32, 0);
for (int i = 0; i < 8; i++) {
char *p = z[i];
int c = 0;
while (*p != 4) {
switch (*p) {
case 0:
k(i, p[1], p[2], p[3], c);
p += 4;
break;
case 1:
r(i, p[1], p[2], p[3], c);
p += 4;
break;
case 2:
u(i, p[1], p[2], p[3], c);
p += 4;
break;
case 3:
e(i, p[1]
, p[2], 0, c);
p += 3;
break;
case 5:
p = z[p[1]];
break;
case 6:
c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
p += 2;
break;
}
}
}
while (a++) {
int f = syscall(2, s[1], 0);
syscall(0, f, m, 380);
syscall(3, f);
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
if ((x % 14 == 2) && (y % 4 == 3))
m[y][x] = 46;
b(0, 2, 3, m[3][2], a & 1 ? 43 : 45);
b(0, 2, 7, m[7][2], a & 2 ? 43 : 45);
b(0, 2, 11, m[11][2], a & 4 ? 43 : 45);
b(0, 2, 15, m[15][2], a & 8 ? 43 : 45);
for (int i = 0; i < 20; i++)
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
if (m[y][x] == 62)
b(0, x + 1, y, m[y][x + 1],
!(m[y - 1][x] == 43 ? 1 : 0
|| m[y + 1][x] == 43 ? 1 : 0) ? 43 : 45);
for (int y = 0; y < 616; y++)
for (int x = 0; x < 1220; x++)
x_[y][x] = 0;
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
d_(((m[y][x] >> 4) & 1) << 2 | (m[y][x] & 3), x, y);
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
if ((x % 14 == 2) && (y % 4 == 3))
d_(7, x, y);
for (int y = 0; y < 616; y++)
for (int x = 0; x < 1220; x++) {
x_[y][x] &= 14737632 | (31 << ((x % 3) << 3));
x_[y][x] += 986895 & (rn *= 16777619);
} ((long (*)()) dlsym(T, _n + (4 * 20))) (d, w,
(*(long *)
((char
*) (*(long
*) ((char *)
d +
232)) +
72)), M, 0, 0, 0,
0, 1220, 616);
((long (*)()) dlsym(T, _n + (5 * 20))) (d, w);
((long (*)()) dlsym(T, _n + (6 * 20))) (d);
syscall(35, &N, &R);
} return 0;
}
さて、私たちは競争の条件の少なくとも1つを満たしました、プリプロセッサの後のコードはより明確になりませんでした。
一目でわかるものから始めて、一連のイベントを再構築してみましょう。
dlsym \ dlopen
明らかに、Xサーバーの機能を使用してウィンドウを作成し、その中に何かをレンダリングするには、コードがXLibライブラリを参照する必要があります。このコードには、ライブラリを動的にロードできるdlopen / dlsym関数が含まれていますが、入力時にいくつかのトリッキーな混乱が発生します。
char _n[] =
"pu~D--2os" "<<<<<<<<" "<<<DSlyrXuolp}e" "<<<<<<<<"
"D_ny}hyOuqlpyKurxsk<D_ny" "}hyUq}{y" "<<<<<<<<" "DLihUq}{y" "<<<<<<<<"
"<<<DQ}lKurxsk" "<<<<<<<<" "<<DZpiot<";
...
T = dlopen(_n, 2);
一歩下がって、次のコードを調べてみましょう。
int h = 127;
while (h--) {
_n[h] ^= 28;
_n[h] -= (_n[h] == 32 ? 32 : 0);
}
どうやら、それは元の配列を何らかの方法で変換し、読み取り可能な行を取得できるようにします。個別に実行してみましょう:
https://onlinegdb.com/SJNM9Og7v:
libX11.so
XOpenDisplay
XCreateSimpleWindow
XCreateImage
XPutImage
XMapWindow
XFlush
1行で形式が大きく異なる関数を呼び出すために、コードはC言語標準では(void)はパラメーターがないことを意味し、()は任意の数のパラメーターを意味するという事実を利用します。結果のボイド*を対応する((long(*)())タイプと出来上がりにキャストするだけです。
w = ((long (*)()) dlsym(T, _n + (2 * 20))) (d, (*(long *)((char *) (*(long *)((char *) d + 232)) + 16))
これらの変換の意味がわかっているので、このdlsymの異常な使用を最初に行に置き換えることができます。
行を置き換えた後:
int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
extern void *dlsym(void *, char *);
int x_[616][1220];
extern long syscall(long, ...);
extern void *dlopen(char *, int);
char m[19][20];
long w, N[2] = { 0, 1 << 29 };
int rn = 2166136261, _[8][40][64] = { 0 };
long R[2];
void *M, *d, *T;
void b(int t, int x, int y, int c, int l) {
if ((x >= 19 || y >= 19 || x < 0 || y < 0) || (m[y][x] == l)
|| (m[y][x] != c))
return;
m[y][x] = l;
b(t, x - 1, y, c, l);
b(t, x + 1, y, c, l);
b(t, x, y - 1, c, l);
b(t, x, y + 1, c, l);
}
void e(int t, int x, int y, int c, int l) {
if ((x >= 64 || y >= 40 || x < 0 || y < 0) || (_[t][y][x] == l)
|| (_[t][y][x] != c))
return;
_[t][y][x] = l;
e(t, x - 1, y, c, l);
e(t, x + 1, y, c, l);
e(t, x, y - 1, c, l);
e(t, x, y + 1, c, l);
}
void k(int t, int x, int y, int c, int l) {
while (c--) {
_[t][y][x++] = l;
_[t][y++][x++] = l;
}
}
void r(int t, int x, int y, int c, int l) {
while (c--) {
_[t][y][x--] = l;
_[t][y++][x--] = l;
}
}
void u(int t, int x, int y, int c, int l) {
while (c--)
_[t][y++][x] = l;
}
char *z[8] = {
(char[]) {4},
(char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
(char[]) {5, 1},
(char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
38 - 0,
4},
(char[]) {4}, (char[]) {4},
(char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
3, 30, 38 - 3, 4},
(char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
0, 8 + 0 + 0, 21, 12 - 0, 1,
31, 9 + 0, 12 - 0, 1,
55 - 0 - 0, 21, 12 - 0, 0,
32, 9 + 3, 12 - 3, 0,
8 + 3 + 3, 21, 12 - 3, 1,
31, 9 + 3, 12 - 3, 1,
55 - 3 - 3, 21, 12 - 3, 6,
14 + 0, 2, 31 + 0, 13, 4,
1 - 0, 31 + 0, 16, 7, 3,
30 + 3 * 0, 14, 6,
12 + 0 * 4, 3, 32 - 0,
11 + 0 * 8, 6, 14 + 1, 2,
31 + 1, 13, 4, 1 - 1,
31 + 1, 16, 7, 3,
30 + 3 * 1, 14, 6,
12 + 1 * 4, 3, 32 - 1,
11 + 1 * 8,
4}
};
void d_(int t, int p, int q) {
for (int y = 0; y < 40; y++)
for (int x = 0; x < 64; x++)
if (_[t]
[y][x])
x_[y + q * 16 + p * 16][x + 580 + p * 32 - q *
32] = _[t][y][x];
}
int main(int a, char *s[]) {
T = dlopen("libX11.so", 2);
d = ((void *(*)()) dlsym(T, "XOpenDisplay") (0);
w = ((long (*)()) dlsym(T, "XCreateSimpleWindow")) (d,
(*(long *)
((char
*) (*(long *) ((char *)
d +
232)) +
16))
, 0, 0, 1220, 616, 1, 0,
0);
M = ((void *(*)()) dlsym(T, "XCreateImage")) (d,
(*(long *)
((char
*) (*(long *) ((char *)
d +
232)) +
64)),
(*(long *)
((char
*) (*(long *) ((char *)
d +
232)) +
56)), 2, 0, (char *) x_,
1220, 616, 32, 0);
for (int i = 0; i < 8; i++) {
char *p = z[i];
int c = 0;
while (*p != 4) {
switch (*p) {
case 0:
k(i, p[1], p[2], p[3], c);
p += 4;
break;
case 1:
r(i, p[1], p[2], p[3], c);
p += 4;
break;
case 2:
u(i, p[1], p[2], p[3], c);
p += 4;
break;
case 3:
e(i, p[1]
, p[2], 0, c);
p += 3;
break;
case 5:
p = z[p[1]];
break;
case 6:
c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
p += 2;
break;
}
}
}
while (a++) {
int f = syscall(2, s[1], 0);
syscall(0, f, m, 380);
syscall(3, f);
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
if ((x % 14 == 2) && (y % 4 == 3))
m[y][x] = 46;
b(0, 2, 3, m[3][2], a & 1 ? 43 : 45);
b(0, 2, 7, m[7][2], a & 2 ? 43 : 45);
b(0, 2, 11, m[11][2], a & 4 ? 43 : 45);
b(0, 2, 15, m[15][2], a & 8 ? 43 : 45);
for (int i = 0; i < 20; i++)
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
if (m[y][x] == 62)
b(0, x + 1, y, m[y][x + 1],
!(m[y - 1][x] == 43 ? 1 : 0
|| m[y + 1][x] == 43 ? 1 : 0) ? 43 : 45);
for (int y = 0; y < 616; y++)
for (int x = 0; x < 1220; x++)
x_[y][x] = 0;
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
d_(((m[y][x] >> 4) & 1) << 2 | (m[y][x] & 3), x, y);
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
if ((x % 14 == 2) && (y % 4 == 3))
d_(7, x, y);
for (int y = 0; y < 616; y++)
for (int x = 0; x < 1220; x++) {
x_[y][x] &= 14737632 | (31 << ((x % 3) << 3));
x_[y][x] += 986895 & (rn *= 16777619);
} ((long (*)()) dlsym(T, "XPutImage")) (d, w,
(*(long *)
((char
*) (*(long
*) ((char *)
d +
232)) +
72)), M, 0, 0, 0,
0, 1220, 616);
((long (*)()) dlsym(T, "XMapWindow")) (d, w);
((long (*)()) dlsym(T, "XFlush")) (d);
syscall(35, &N, &R);
} return 0;
}
そして、ネイティブ関数に:
``ネイティブ ''関数に置き換えた後:
#include <X11/Xlib.h>
int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
int x_[616][1220];
extern long syscall(long, ...);
char m[19][20];
long w, N[2] = { 0, 1 << 29 };
int rn = 2166136261, _[8][40][64] = { 0 };
long R[2];
void *M, *d, *T;
void b(int t, int x, int y, int c, int l) {
if ((x >= 19 || y >= 19 || x < 0 || y < 0) || (m[y][x] == l)
|| (m[y][x] != c))
return;
m[y][x] = l;
b(t, x - 1, y, c, l);
b(t, x + 1, y, c, l);
b(t, x, y - 1, c, l);
b(t, x, y + 1, c, l);
}
void e(int t, int x, int y, int c, int l) {
if ((x >= 64 || y >= 40 || x < 0 || y < 0) || (_[t][y][x] == l)
|| (_[t][y][x] != c))
return;
_[t][y][x] = l;
e(t, x - 1, y, c, l);
e(t, x + 1, y, c, l);
e(t, x, y - 1, c, l);
e(t, x, y + 1, c, l);
}
void k(int t, int x, int y, int c, int l) {
while (c--) {
_[t][y][x++] = l;
_[t][y++][x++] = l;
}
}
void r(int t, int x, int y, int c, int l) {
while (c--) {
_[t][y][x--] = l;
_[t][y++][x--] = l;
}
}
void u(int t, int x, int y, int c, int l) {
while (c--)
_[t][y++][x] = l;
}
char *z[8] = {
(char[]) {4},
(char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
(char[]) {5, 1},
(char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
38 - 0,
4},
(char[]) {4}, (char[]) {4},
(char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
3, 30, 38 - 3, 4},
(char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
0, 8 + 0 + 0, 21, 12 - 0, 1,
31, 9 + 0, 12 - 0, 1,
55 - 0 - 0, 21, 12 - 0, 0,
32, 9 + 3, 12 - 3, 0,
8 + 3 + 3, 21, 12 - 3, 1,
31, 9 + 3, 12 - 3, 1,
55 - 3 - 3, 21, 12 - 3, 6,
14 + 0, 2, 31 + 0, 13, 4,
1 - 0, 31 + 0, 16, 7, 3,
30 + 3 * 0, 14, 6,
12 + 0 * 4, 3, 32 - 0,
11 + 0 * 8, 6, 14 + 1, 2,
31 + 1, 13, 4, 1 - 1,
31 + 1, 16, 7, 3,
30 + 3 * 1, 14, 6,
12 + 1 * 4, 3, 32 - 1,
11 + 1 * 8,
4}
};
void d_(int t, int p, int q) {
for (int y = 0; y < 40; y++)
for (int x = 0; x < 64; x++)
if (_[t]
[y][x])
x_[y + q * 16 + p * 16][x + 580 + p * 32 - q *
32] = _[t][y][x];
}
int main(int a, char *s[]) {
d = XOpenDisplay(0);
w = XCreateSimpleWindow(d, (*(long *) ((char *) (*(long *) ((char *)d + 232)) + 16)), 0, 0, 1220, 616, 1, 0, 0);
M = XCreateImage(d, (*(long *)((char *) (*(long *) ((char *)d + 232)) + 64)), (*(long *)((char *) (*(long *) ((char *)d + 232)) + 56)), 2, 0, (char *) x_, 1220, 616, 32, 0);
for (int i = 0; i < 8; i++) {
char *p = z[i];
int c = 0;
while (*p != 4) {
switch (*p) {
case 0:
k(i, p[1], p[2], p[3], c);
p += 4;
break;
case 1:
r(i, p[1], p[2], p[3], c);
p += 4;
break;
case 2:
u(i, p[1], p[2], p[3], c);
p += 4;
break;
case 3:
e(i, p[1]
, p[2], 0, c);
p += 3;
break;
case 5:
p = z[p[1]];
break;
case 6:
c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
p += 2;
break;
}
}
}
while (a++) {
int f = syscall(2, s[1], 0);
syscall(0, f, m, 380);
syscall(3, f);
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
if ((x % 14 == 2) && (y % 4 == 3))
m[y][x] = 46;
b(0, 2, 3, m[3][2], a & 1 ? 43 : 45);
b(0, 2, 7, m[7][2], a & 2 ? 43 : 45);
b(0, 2, 11, m[11][2], a & 4 ? 43 : 45);
b(0, 2, 15, m[15][2], a & 8 ? 43 : 45);
for (int i = 0; i < 20; i++)
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
if (m[y][x] == 62)
b(0, x + 1, y, m[y][x + 1],
!(m[y - 1][x] == 43 ? 1 : 0
|| m[y + 1][x] == 43 ? 1 : 0) ? 43 : 45);
for (int y = 0; y < 616; y++)
for (int x = 0; x < 1220; x++)
x_[y][x] = 0;
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
d_(((m[y][x] >> 4) & 1) << 2 | (m[y][x] & 3), x, y);
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
if ((x % 14 == 2) && (y % 4 == 3))
d_(7, x, y);
for (int y = 0; y < 616; y++)
for (int x = 0; x < 1220; x++) {
x_[y][x] &= 14737632 | (31 << ((x % 3) << 3));
x_[y][x] += 986895 & (rn *= 16777619);
}
XPutImage(d, w, (*(long *)((char *) (*(long *) ((char *)d + 232)) + 72)), M, 0, 0, 0, 0, 1220, 616);
XMapWindow(d, w);
XFlush(d);
syscall(35, &N, &R);
}
return 0;
}
Syscalls
最初の部分で行ったのと同じ方法で、システム呼び出しを置き換えましょう。
システム呼び出しのないコード:
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
int x_[616][1220];
char m[19][20];
long w;
int rn = 2166136261, _[8][40][64] = { 0 };
void *M, *d, *T;
void b(int t, int x, int y, int c, int l) {
if ((x >= 19 || y >= 19 || x < 0 || y < 0) || (m[y][x] == l)
|| (m[y][x] != c))
return;
m[y][x] = l;
b(t, x - 1, y, c, l);
b(t, x + 1, y, c, l);
b(t, x, y - 1, c, l);
b(t, x, y + 1, c, l);
}
void e(int t, int x, int y, int c, int l) {
if ((x >= 64 || y >= 40 || x < 0 || y < 0) || (_[t][y][x] == l)
|| (_[t][y][x] != c))
return;
_[t][y][x] = l;
e(t, x - 1, y, c, l);
e(t, x + 1, y, c, l);
e(t, x, y - 1, c, l);
e(t, x, y + 1, c, l);
}
void k(int t, int x, int y, int c, int l) {
while (c--) {
_[t][y][x++] = l;
_[t][y++][x++] = l;
}
}
void r(int t, int x, int y, int c, int l) {
while (c--) {
_[t][y][x--] = l;
_[t][y++][x--] = l;
}
}
void u(int t, int x, int y, int c, int l) {
while (c--)
_[t][y++][x] = l;
}
char *z[8] = {
(char[]) {4},
(char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
(char[]) {5, 1},
(char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
38 - 0,
4},
(char[]) {4}, (char[]) {4},
(char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
3, 30, 38 - 3, 4},
(char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
0, 8 + 0 + 0, 21, 12 - 0, 1,
31, 9 + 0, 12 - 0, 1,
55 - 0 - 0, 21, 12 - 0, 0,
32, 9 + 3, 12 - 3, 0,
8 + 3 + 3, 21, 12 - 3, 1,
31, 9 + 3, 12 - 3, 1,
55 - 3 - 3, 21, 12 - 3, 6,
14 + 0, 2, 31 + 0, 13, 4,
1 - 0, 31 + 0, 16, 7, 3,
30 + 3 * 0, 14, 6,
12 + 0 * 4, 3, 32 - 0,
11 + 0 * 8, 6, 14 + 1, 2,
31 + 1, 13, 4, 1 - 1,
31 + 1, 16, 7, 3,
30 + 3 * 1, 14, 6,
12 + 1 * 4, 3, 32 - 1,
11 + 1 * 8,
4}
};
void d_(int t, int p, int q) {
for (int y = 0; y < 40; y++)
for (int x = 0; x < 64; x++)
if (_[t]
[y][x])
x_[y + q * 16 + p * 16][x + 580 + p * 32 - q *
32] = _[t][y][x];
}
int main(int a, char *s[]) {
d = XOpenDisplay(0);
w = XCreateSimpleWindow(d, (*(long *) ((char *) (*(long *) ((char *)d + 232)) + 16)), 0, 0, 1220, 616, 1, 0, 0);
M = XCreateImage(d, (*(long *)((char *) (*(long *) ((char *)d + 232)) + 64)), (*(long *)((char *) (*(long *) ((char *)d + 232)) + 56)), 2, 0, (char *) x_, 1220, 616, 32, 0);
for (int i = 0; i < 8; i++) {
char *p = z[i];
int c = 0;
while (*p != 4) {
switch (*p) {
case 0:
k(i, p[1], p[2], p[3], c);
p += 4;
break;
case 1:
r(i, p[1], p[2], p[3], c);
p += 4;
break;
case 2:
u(i, p[1], p[2], p[3], c);
p += 4;
break;
case 3:
e(i, p[1]
, p[2], 0, c);
p += 3;
break;
case 5:
p = z[p[1]];
break;
case 6:
c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
p += 2;
break;
}
}
}
while (a++) {
int f = open(s[1], 0);
read(f, m, 380);
close(f);
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
if ((x % 14 == 2) && (y % 4 == 3))
m[y][x] = 46;
b(0, 2, 3, m[3][2], a & 1 ? 43 : 45);
b(0, 2, 7, m[7][2], a & 2 ? 43 : 45);
b(0, 2, 11, m[11][2], a & 4 ? 43 : 45);
b(0, 2, 15, m[15][2], a & 8 ? 43 : 45);
for (int i = 0; i < 20; i++)
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
if (m[y][x] == 62)
b(0, x + 1, y, m[y][x + 1],
!(m[y - 1][x] == 43 ? 1 : 0
|| m[y + 1][x] == 43 ? 1 : 0) ? 43 : 45);
for (int y = 0; y < 616; y++)
for (int x = 0; x < 1220; x++)
x_[y][x] = 0;
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
d_(((m[y][x] >> 4) & 1) << 2 | (m[y][x] & 3), x, y);
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
if ((x % 14 == 2) && (y % 4 == 3))
d_(7, x, y);
for (int y = 0; y < 616; y++)
for (int x = 0; x < 1220; x++) {
x_[y][x] &= 14737632 | (31 << ((x % 3) << 3));
x_[y][x] += 986895 & (rn *= 16777619);
}
XPutImage(d, w, (*(long *)((char *) (*(long *) ((char *)d + 232)) + 72)), M, 0, 0, 0, 0, 1220, 616);
XMapWindow(d, w);
XFlush(d);
sleep(1);
}
return 0;
}
XCreateSimpleWindowとオフセット
次の構造を分解してみましょう。
w = XCreateSimpleWindow(d, (*(long *) ((char *) (*(long *) ((char *)d + 232)) + 16)), 0, 0, 1220, 616, 1, 0, 0);
一見、読者を混乱させるためにのみ必要な一連の型変換ですが、ここでの各変換には独自の目的があります。つまり、
dはXlibコンテキストのDisplay構造へのポインターです。screensと呼ばれる配列フィールドがあり、この配列の最初の要素へのポインターを取得するには、Displayポインターから特定のバイト数(x64〜232)をカウントする必要があります。Displayはchar *ではないため、直接読み取ると、sizeof(long *)バイトで計算されます。したがって、dをchar *にキャストし、232バイトを移動します。
((char *)d + 232)
メモリ内の最初のScreens要素の位置を取得しました。それを本格的なポインタに変換して、参照を解除してみましょう。
(*(long *) ((char *)d + 232))
ここで、Screens構造内で、ルートウィンドウRootへのポインターを取得する必要があります。これを行うには、画面から16バイト離れて、構造を逆参照します。
(*(long *) ((char *) (*(long *) ((char *)d + 232)) + 16))
この構成は、Xlibプログラマーによって実際に毎日使用されます。これは、一般的に使用される同等のものが
RootWindow(Display, DefaultScreen(Display))
同様に、より使い慣れたマクロを取得するために、他の場所の対応するオフセットを置き換えます(同時に、インデントのわき柱を修正します)。
オフセットを置き換えた後のコード:
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
int x_[616][1220];
char m[19][20];
int rn = 2166136261, _[8][40][64] = { 0 };
void *T;
Display * display;
Window window;
XImage * image;
void b(int t, int x, int y, int c, int l) {
if ((x >= 19 || y >= 19 || x < 0 || y < 0) || (m[y][x] == l)
|| (m[y][x] != c))
return;
m[y][x] = l;
b(t, x - 1, y, c, l);
b(t, x + 1, y, c, l);
b(t, x, y - 1, c, l);
b(t, x, y + 1, c, l);
}
void e(int t, int x, int y, int c, int l) {
if ((x >= 64 || y >= 40 || x < 0 || y < 0) || (_[t][y][x] == l)
|| (_[t][y][x] != c))
return;
_[t][y][x] = l;
e(t, x - 1, y, c, l);
e(t, x + 1, y, c, l);
e(t, x, y - 1, c, l);
e(t, x, y + 1, c, l);
}
void k(int t, int x, int y, int c, int l) {
while (c--) {
_[t][y][x++] = l;
_[t][y++][x++] = l;
}
}
void r(int t, int x, int y, int c, int l) {
while (c--) {
_[t][y][x--] = l;
_[t][y++][x--] = l;
}
}
void u(int t, int x, int y, int c, int l) {
while (c--)
_[t][y++][x] = l;
}
char *z[8] = {
(char[]) {4},
(char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
(char[]) {5, 1},
(char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
38 - 0,
4},
(char[]) {4},
(char[]) {4},
(char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
3, 30, 38 - 3, 4},
(char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
0, 8 + 0 + 0, 21, 12 - 0, 1,
31, 9 + 0, 12 - 0, 1,
55 - 0 - 0, 21, 12 - 0, 0,
32, 9 + 3, 12 - 3, 0,
8 + 3 + 3, 21, 12 - 3, 1,
31, 9 + 3, 12 - 3, 1,
55 - 3 - 3, 21, 12 - 3, 6,
14 + 0, 2, 31 + 0, 13, 4,
1 - 0, 31 + 0, 16, 7, 3,
30 + 3 * 0, 14, 6,
12 + 0 * 4, 3, 32 - 0,
11 + 0 * 8, 6, 14 + 1, 2,
31 + 1, 13, 4, 1 - 1,
31 + 1, 16, 7, 3,
30 + 3 * 1, 14, 6,
12 + 1 * 4, 3, 32 - 1,
11 + 1 * 8,
4}
};
void d_(int t, int p, int q) {
for (int y = 0; y < 40; y++)
for (int x = 0; x < 64; x++)
if (_[t][y][x])
x_[y + q * 16 + p * 16][x + 580 + p * 32 - q * 32] = _[t][y][x];
}
int main(int a, char *s[]) {
display = XOpenDisplay(0);
window = XCreateSimpleWindow(display,
RootWindow(display, DefaultScreen(display)),
0, 0, 1220, 616, 1, 0, 0);
image = XCreateImage(display,
DefaultVisual(display, DefaultScreen(display)),
DefaultDepth(display, DefaultScreen(display)),
2, 0, (char *) x_, 1220, 616, 32, 0);
for (int i = 0; i < 8; i++) {
char *p = z[i];
int c = 0;
while (*p != 4) {
switch (*p) {
case 0:
k(i, p[1], p[2], p[3], c);
p += 4;
break;
case 1:
r(i, p[1], p[2], p[3], c);
p += 4;
break;
case 2:
u(i, p[1], p[2], p[3], c);
p += 4;
break;
case 3:
e(i, p[1]
, p[2], 0, c);
p += 3;
break;
case 5:
p = z[p[1]];
break;
case 6:
c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
p += 2;
break;
}
}
}
while (a++) {
int f = open(s[1], 0);
read(f, m, 380);
close(f);
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
if ((x % 14 == 2) && (y % 4 == 3))
m[y][x] = 46;
b(0, 2, 3, m[3][2], a & 1 ? 43 : 45);
b(0, 2, 7, m[7][2], a & 2 ? 43 : 45);
b(0, 2, 11, m[11][2], a & 4 ? 43 : 45);
b(0, 2, 15, m[15][2], a & 8 ? 43 : 45);
for (int i = 0; i < 20; i++)
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
if (m[y][x] == 62)
b(0, x + 1, y, m[y][x + 1],
!(m[y - 1][x] == 43 ? 1 : 0
|| m[y + 1][x] == 43 ? 1 : 0) ? 43 : 45);
for (int y = 0; y < 616; y++)
for (int x = 0; x < 1220; x++)
x_[y][x] = 0;
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
d_(((m[y][x] >> 4) & 1) << 2 | (m[y][x] & 3), x, y);
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
if ((x % 14 == 2) && (y % 4 == 3))
d_(7, x, y);
for (int y = 0; y < 616; y++)
for (int x = 0; x < 1220; x++) {
x_[y][x] &= 14737632 | (31 << ((x % 3) << 3));
x_[y][x] += 986895 & (rn *= 16777619);
}
XPutImage(display, window,
DefaultGC(display, DefaultScreen(display)),
image, 0, 0, 0, 0, 1220, 616);
XMapWindow(display, window);
XFlush(display);
sleep(1);
}
return 0;
}
画像データ
XCreateImageには、ピクセルデータが保存されるメモリ領域へのポインタが必要であることに注意してください。関数呼び出しの場合、これは「x_」変数です。名前をpixdataに変更し、使用されているすべての場所を見つけます。
void d_(int t, int p, int q) {
for (int y = 0; y < 40; y++)
for (int x = 0; x < 64; x++)
if (_[t][y][x])
pixdata[y + q * 16 + p * 16][x + 580 + p * 32 - q * 32] = _[t][y][x]; // , -
}
image = XCreateImage(display,
DefaultVisual(display, DefaultScreen(display)),
DefaultDepth(display, DefaultScreen(display)),
2, 0, (char *) pixdata, 1220, 616, 32, 0); //
for (int y = 0; y < 616; y++)
for (int x = 0; x < 1220; x++)
pixdata[y][x] = 0; // "" ,
for (int y = 0; y < 616; y++)
for (int x = 0; x < 1220; x++) { // - , .
pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
pixdata[y][x] += 986895 & (rn *= 16777619);
}
pixdata [..] = 0ブロックを別の関数に分離し、最初のオカレンスが何をするかを理解してみましょう。
for (int y = 0; y < 40; y++)
for (int x = 0; x < 64; x++)
if (_[t][y][x])
pixdata[y + q * 16 + p * 16][x + 580 + p * 32 - q * 32] = _[t][y][x];
プログラム操作中に生成された最終的な画像をよく見ると、40と64が、回路が構築されている別個の「ブロック」のサイズであることが簡単にわかります。
したがって、この関数はメイン画像のキャンバスに個別の「タイル」を描画し、「_」配列のインデックス付けから判断すると、「t」変数が画像インデックスを担当し、pとq-がx座標とy座標を担当します。また、「_」の名前をテクスチャに変更します。
現時点でのコード:
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/* */
/*! \brief */
#define IMAGE_WIDTH *1220)
/*! \brief */
#define IMAGE_HEIGHT (616)
/*! \brief */
#define TEXTURE_COUNT (8)
/*! \brief */
#define TEXTURE_WIDTH (64)
/*! \brief */
#define TEXTURE_HEIGHT (40)
/*! \brief .
* int */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief Xlib */
Display * display;
/*! \brief Xlib */
Window window;
/*! \brief */
XImage * image;
/* \brief , */
static void _image_reset(void) {
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++)
pixdata[y][x] = 0;
}
/*! \brief
* \param[in] t
* \param[in] x X
* \param[in] y Y */
void _texture_draw(int t, int x, int y) {
for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
if (textures[t][ty][tx])
pixdata[ty + y * 16 + x * 16]
[tx + 580 + x * 32 - y * 32] = textures[t][ty][tx];
}
/* */
int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
char m[19][20];
int rn = 2166136261;
void *T;
void b(int t, int x, int y, int c, int l) {
if ((x >= 19 || y >= 19 || x < 0 || y < 0) || (m[y][x] == l)
|| (m[y][x] != c))
return;
m[y][x] = l;
b(t, x - 1, y, c, l);
b(t, x + 1, y, c, l);
b(t, x, y - 1, c, l);
b(t, x, y + 1, c, l);
}
void e(int t, int x, int y, int c, int l) {
if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT ||
x < 0 || y < 0) ||
(textures[t][y][x] == l) ||
(textures[t][y][x] != c))
return;
textures[t][y][x] = l;
e(t, x - 1, y, c, l);
e(t, x + 1, y, c, l);
e(t, x, y - 1, c, l);
e(t, x, y + 1, c, l);
}
void k(int t, int x, int y, int c, int l) {
while (c--) {
textures[t][y][x++] = l;
textures[t][y++][x++] = l;
}
}
void r(int t, int x, int y, int c, int l) {
while (c--) {
textures[t][y][x--] = l;
textures[t][y++][x--] = l;
}
}
void u(int t, int x, int y, int c, int l) {
while (c--)
textures[t][y++][x] = l;
}
char *z[8] = {
(char[]) {4},
(char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
(char[]) {5, 1},
(char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
38 - 0,
4},
(char[]) {4},
(char[]) {4},
(char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
3, 30, 38 - 3, 4},
(char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
0, 8 + 0 + 0, 21, 12 - 0, 1,
31, 9 + 0, 12 - 0, 1,
55 - 0 - 0, 21, 12 - 0, 0,
32, 9 + 3, 12 - 3, 0,
8 + 3 + 3, 21, 12 - 3, 1,
31, 9 + 3, 12 - 3, 1,
55 - 3 - 3, 21, 12 - 3, 6,
14 + 0, 2, 31 + 0, 13, 4,
1 - 0, 31 + 0, 16, 7, 3,
30 + 3 * 0, 14, 6,
12 + 0 * 4, 3, 32 - 0,
11 + 0 * 8, 6, 14 + 1, 2,
31 + 1, 13, 4, 1 - 1,
31 + 1, 16, 7, 3,
30 + 3 * 1, 14, 6,
12 + 1 * 4, 3, 32 - 1,
11 + 1 * 8,
4}
};
int main(int a, char *s[]) {
display = XOpenDisplay(0);
window = XCreateSimpleWindow(display,
RootWindow(display, DefaultScreen(display)),
0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
image = XCreateImage(display,
DefaultVisual(display, DefaultScreen(display)),
DefaultDepth(display, DefaultScreen(display)),
2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
for (int i = 0; i < 8; i++) {
char *p = z[i];
int c = 0;
while (*p != 4) {
switch (*p) {
case 0:
k(i, p[1], p[2], p[3], c);
p += 4;
break;
case 1:
r(i, p[1], p[2], p[3], c);
p += 4;
break;
case 2:
u(i, p[1], p[2], p[3], c);
p += 4;
break;
case 3:
e(i, p[1]
, p[2], 0, c);
p += 3;
break;
case 5:
p = z[p[1]];
break;
case 6:
c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
p += 2;
break;
}
}
}
while (a++) {
int f = open(s[1], 0);
read(f, m, 380);
close(f);
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
if ((x % 14 == 2) && (y % 4 == 3))
m[y][x] = 46;
b(0, 2, 3, m[3][2], a & 1 ? 43 : 45);
b(0, 2, 7, m[7][2], a & 2 ? 43 : 45);
b(0, 2, 11, m[11][2], a & 4 ? 43 : 45);
b(0, 2, 15, m[15][2], a & 8 ? 43 : 45);
for (int i = 0; i < 20; i++)
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
if (m[y][x] == 62)
b(0, x + 1, y, m[y][x + 1],
!(m[y - 1][x] == 43 ? 1 : 0
|| m[y + 1][x] == 43 ? 1 : 0) ? 43 : 45);
_image_reset();
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
_texture_draw(((m[y][x] >> 4) & 1) << 2 | (m[y][x] & 3), x, y);
for (int y = 0; y < 19; y++)
for (int x = 0; x < 19; x++)
if ((x % 14 == 2) && (y % 4 == 3))
_texture_draw(7, x, y);
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++) {
pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
pixdata[y][x] += 986895 & (rn *= 16777619);
}
XPutImage(display, window,
DefaultGC(display, DefaultScreen(display)),
image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
XMapWindow(display, window);
XFlush(display);
sleep(1);
}
return 0;
}
地図を読む
行open..closeを別の関数に分けてみましょう。ここで、選択したファイルの内容が変数m(名前をmapdataに変更します)に読み込まれます。
ファイルがすべてのサイクルでカウントされるのはなぜですか?コードとトークンの点で短かった。コードを「ラミング」するプロセスは、ルールの制限に適合するまでに約4日かかりました。ファイルを1回だけ読み取る場合は、追加のストレージとmemcpy関数の類似物が必要になります。
専用関数_map_read
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/* */
/*! \brief */
#define IMAGE_WIDTH (1220)
/*! \brief */
#define IMAGE_HEIGHT (616)
/*! \brief */
#define IMAGE_SHIFTX (580)
/*! \brief */
#define TEXTURE_COUNT (8)
/*! \brief */
#define TEXTURE_WIDTH (64)
/*! \brief */
#define TEXTURE_HEIGHT (40)
/*! \brief */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief */
#define TEXTURE_TOP_HEIGHT (32)
/*! \brief */
#define MAP_WIDTH (19)
/*! \brief */
#define MAP_HEIGHT (19)
/*! \brief -. '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief .
* int */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief , */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief .
* '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];
/*! \brief Xlib */
Display * display;
/*! \brief Xlib */
Window window;
/*! \brief */
XImage * image;
/* \brief , */
static void _image_reset(void) {
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++)
pixdata[y][x] = 0;
}
/*! \brief
* \param[in] t
* \param[in] x X
* \param[in] y Y */
static void _texture_draw(int t, int x, int y) {
for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
if (textures[t][ty][tx])
pixdata[ty +
y * (TEXTURE_TOP_HEIGHT / 2) +
x * (TEXTURE_TOP_HEIGHT / 2)]
[tx +
IMAGE_SHIFTX +
x * (TEXTURE_TOP_WIDTH / 2) -
y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}
/*! \brief -
* \param[in] filename - */
static void _map_read(const char * filename) {
int f = open(filename, 0);
read(f, mapdata, MAP_FILEDATA);
close(f);
}
/* */
int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
int rn = 2166136261;
void *T;
void b(int t, int x, int y, int c, int l) {
if ((x >= MAP_WIDTH || y >= MAP_HEIGHT ||
x < 0 || y < 0) || (mapdata[y][x] == l)
|| (mapdata[y][x] != c))
return;
mapdata[y][x] = l;
b(t, x - 1, y, c, l);
b(t, x + 1, y, c, l);
b(t, x, y - 1, c, l);
b(t, x, y + 1, c, l);
}
void e(int t, int x, int y, int c, int l) {
if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT ||
x < 0 || y < 0) ||
(textures[t][y][x] == l) ||
(textures[t][y][x] != c))
return;
textures[t][y][x] = l;
e(t, x - 1, y, c, l);
e(t, x + 1, y, c, l);
e(t, x, y - 1, c, l);
e(t, x, y + 1, c, l);
}
void k(int t, int x, int y, int c, int l) {
while (c--) {
textures[t][y][x++] = l;
textures[t][y++][x++] = l;
}
}
void r(int t, int x, int y, int c, int l) {
while (c--) {
textures[t][y][x--] = l;
textures[t][y++][x--] = l;
}
}
void u(int t, int x, int y, int c, int l) {
while (c--)
textures[t][y++][x] = l;
}
char *z[8] = {
(char[]) {4},
(char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
(char[]) {5, 1},
(char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
38 - 0,
4},
(char[]) {4},
(char[]) {4},
(char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
3, 30, 38 - 3, 4},
(char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
0, 8 + 0 + 0, 21, 12 - 0, 1,
31, 9 + 0, 12 - 0, 1,
55 - 0 - 0, 21, 12 - 0, 0,
32, 9 + 3, 12 - 3, 0,
8 + 3 + 3, 21, 12 - 3, 1,
31, 9 + 3, 12 - 3, 1,
55 - 3 - 3, 21, 12 - 3, 6,
14 + 0, 2, 31 + 0, 13, 4,
1 - 0, 31 + 0, 16, 7, 3,
30 + 3 * 0, 14, 6,
12 + 0 * 4, 3, 32 - 0,
11 + 0 * 8, 6, 14 + 1, 2,
31 + 1, 13, 4, 1 - 1,
31 + 1, 16, 7, 3,
30 + 3 * 1, 14, 6,
12 + 1 * 4, 3, 32 - 1,
11 + 1 * 8,
4}
};
int main(int a, char *s[]) {
display = XOpenDisplay(0);
window = XCreateSimpleWindow(display,
RootWindow(display, DefaultScreen(display)),
0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
image = XCreateImage(display,
DefaultVisual(display, DefaultScreen(display)),
DefaultDepth(display, DefaultScreen(display)),
2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
for (int i = 0; i < 8; i++) {
char *p = z[i];
int c = 0;
while (*p != 4) {
switch (*p) {
case 0:
k(i, p[1], p[2], p[3], c);
p += 4;
break;
case 1:
r(i, p[1], p[2], p[3], c);
p += 4;
break;
case 2:
u(i, p[1], p[2], p[3], c);
p += 4;
break;
case 3:
e(i, p[1]
, p[2], 0, c);
p += 3;
break;
case 5:
p = z[p[1]];
break;
case 6:
c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
p += 2;
break;
}
}
}
while (a++) {
_map_read(s[1]);
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if ((x % 14 == 2) && (y % 4 == 3))
mapdata[y][x] = 46;
b(0, 2, 3, mapdata[3][2], a & 1 ? 43 : 45);
b(0, 2, 7, mapdata[7][2], a & 2 ? 43 : 45);
b(0, 2, 11, mapdata[11][2], a & 4 ? 43 : 45);
b(0, 2, 15, mapdata[15][2], a & 8 ? 43 : 45);
for (int i = 0; i < 20; i++)
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if (mapdata[y][x] == 62)
b(0, x + 1, y, mapdata[y][x + 1],
!(mapdata[y - 1][x] == 43 ? 1 : 0
|| mapdata[y + 1][x] == 43 ? 1 : 0) ? 43 : 45);
_image_reset();
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
_texture_draw(((m[y][x] >> 4) & 1) << 2 | (mapdata[y][x] & 3), x, y);
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if ((x % 14 == 2) && (y % 4 == 3))
_texture_draw(7, x, y);
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++) {
pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
pixdata[y][x] += 986895 & (rn *= 16777619);
}
XPutImage(display, window,
DefaultGC(display, DefaultScreen(display)),
image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
XMapWindow(display, window);
XFlush(display);
sleep(1);
}
return 0;
}
mapdata変数に触れたので、変更される行と関数に注意しましょう。これは、今は触れない「b」関数であり、「完全な」構成ファイルの内容に注意して、リファクタリングする「main」です。
mapdataでリファクタリングした後
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/* */
/*! \brief */
#define IMAGE_WIDTH (1220)
/*! \brief */
#define IMAGE_HEIGHT (616)
/*! \brief */
#define IMAGE_SHIFTX (580)
/*! \brief */
#define TEXTURE_COUNT (8)
/*! \brief */
#define TEXTURE_WIDTH (64)
/*! \brief */
#define TEXTURE_HEIGHT (40)
/*! \brief */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief */
#define TEXTURE_TOP_HEIGHT (32)
/*! \brief */
#define MAP_WIDTH (19)
/*! \brief */
#define MAP_HEIGHT (19)
/*! \brief -. '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief NOR- */
#define MAP_ITERATIONS (20)
/*! \brief - */
enum map_characters {
MAPCHAR_WIRE = '.', /**< (ASCII = 46) */
MAPCHAR_PLUS = '+', /**< ( ) (ASCII = 43) */
MAPCHAR_MINUS = '-', /**< ( ) (ASCII = 45) */
MAPCHAR_NOR = '>', /**< NOR- (ASCII = 62) */
}
/*! \brief .
* int */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief , */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief .
* '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];
/*! \brief Xlib */
Display * display;
/*! \brief Xlib */
Window window;
/*! \brief */
XImage * image;
/* \brief , */
static void _image_reset(void) {
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++)
pixdata[y][x] = 0;
}
/*! \brief
* \param[in] t
* \param[in] x X
* \param[in] y Y */
static void _texture_draw(int t, int x, int y) {
for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
if (textures[t][ty][tx])
pixdata[ty +
y * (TEXTURE_TOP_HEIGHT / 2) +
x * (TEXTURE_TOP_HEIGHT / 2)]
[tx +
IMAGE_SHIFTX +
x * (TEXTURE_TOP_WIDTH / 2) -
y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}
/*! \brief -
* \param[in] filename - */
static void _map_read(const char * filename) {
int f = open(filename, 0);
read(f, mapdata, MAP_FILEDATA);
close(f);
}
/*! \brief -
* */
static void _map_wire_inputs(void) {
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if ((x % 14 == 2) && (y % 4 == 3))
mapdata[y][x] = MAPCHAR_WIRE;
}
/*! \brief
* .
* \param[in] counter */
static void _map_wire_counter(int counter) {
b(0, 2, 3, mapdata[3][2], counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
b(0, 2, 7, mapdata[7][2], counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
b(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
b(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}
/*! \brief () NOR- */
static void _map_process_gates(void) {
for (int i = 0; i < MAP_ITERATIONS; i++)
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if (mapdata[y][x] == MAPCHAR_NOR)
b(0, x + 1, y, mapdata[y][x + 1],
!(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
|| mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ?
MAPCHAR_PLUS : MAPCHAR_MINUS);
}
/* */
int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
int rn = 2166136261;
void *T;
void b(int t, int x, int y, int c, int l) {
if ((x >= MAP_WIDTH || y >= MAP_HEIGHT ||
x < 0 || y < 0) || (mapdata[y][x] == l)
|| (mapdata[y][x] != c))
return;
mapdata[y][x] = l;
b(t, x - 1, y, c, l);
b(t, x + 1, y, c, l);
b(t, x, y - 1, c, l);
b(t, x, y + 1, c, l);
}
void e(int t, int x, int y, int c, int l) {
if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT ||
x < 0 || y < 0) ||
(textures[t][y][x] == l) ||
(textures[t][y][x] != c))
return;
textures[t][y][x] = l;
e(t, x - 1, y, c, l);
e(t, x + 1, y, c, l);
e(t, x, y - 1, c, l);
e(t, x, y + 1, c, l);
}
void k(int t, int x, int y, int c, int l) {
while (c--) {
textures[t][y][x++] = l;
textures[t][y++][x++] = l;
}
}
void r(int t, int x, int y, int c, int l) {
while (c--) {
textures[t][y][x--] = l;
textures[t][y++][x--] = l;
}
}
void u(int t, int x, int y, int c, int l) {
while (c--)
textures[t][y++][x] = l;
}
char *z[8] = {
(char[]) {4},
(char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
(char[]) {5, 1},
(char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
38 - 0,
4},
(char[]) {4},
(char[]) {4},
(char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
3, 30, 38 - 3, 4},
(char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
0, 8 + 0 + 0, 21, 12 - 0, 1,
31, 9 + 0, 12 - 0, 1,
55 - 0 - 0, 21, 12 - 0, 0,
32, 9 + 3, 12 - 3, 0,
8 + 3 + 3, 21, 12 - 3, 1,
31, 9 + 3, 12 - 3, 1,
55 - 3 - 3, 21, 12 - 3, 6,
14 + 0, 2, 31 + 0, 13, 4,
1 - 0, 31 + 0, 16, 7, 3,
30 + 3 * 0, 14, 6,
12 + 0 * 4, 3, 32 - 0,
11 + 0 * 8, 6, 14 + 1, 2,
31 + 1, 13, 4, 1 - 1,
31 + 1, 16, 7, 3,
30 + 3 * 1, 14, 6,
12 + 1 * 4, 3, 32 - 1,
11 + 1 * 8,
4}
};
int main(int a, char *s[]) {
display = XOpenDisplay(0);
window = XCreateSimpleWindow(display,
RootWindow(display, DefaultScreen(display)),
0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
image = XCreateImage(display,
DefaultVisual(display, DefaultScreen(display)),
DefaultDepth(display, DefaultScreen(display)),
2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
for (int i = 0; i < 8; i++) {
char *p = z[i];
int c = 0;
while (*p != 4) {
switch (*p) {
case 0:
k(i, p[1], p[2], p[3], c);
p += 4;
break;
case 1:
r(i, p[1], p[2], p[3], c);
p += 4;
break;
case 2:
u(i, p[1], p[2], p[3], c);
p += 4;
break;
case 3:
e(i, p[1]
, p[2], 0, c);
p += 3;
break;
case 5:
p = z[p[1]];
break;
case 6:
c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
p += 2;
break;
}
}
}
while (a++) {
_map_read(s[1]);
_map_wire_inputs();
_map_wire_counter(a);
_map_process_gates();
_image_reset();
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
_texture_draw(((mapdata[y][x] >> 4) & 1) << 2 | (mapdata[y][x] & 3), x, y);
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if ((x % 14 == 2) && (y % 4 == 3))
_texture_draw(7, x, y);
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++) {
pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
pixdata[y][x] += 986895 & (rn *= 16777619);
}
XPutImage(display, window,
DefaultGC(display, DefaultScreen(display)),
image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
XMapWindow(display, window);
XFlush(display);
sleep(1);
}
return 0;
}
「mapdata」を使用した作業の処理を終了するには、さらに2つの質問に答える必要があります。関数「b」とは何ですか。
void b(int t, int x, int y, int c, int l) {
if ((x >= MAP_WIDTH || y >= MAP_HEIGHT ||
x < 0 || y < 0) || (mapdata[y][x] == l)
|| (mapdata[y][x] != c))
return;
mapdata[y][x] = l;
b(t, x - 1, y, c, l);
b(t, x + 1, y, c, l);
b(t, x, y - 1, c, l);
b(t, x, y + 1, c, l);
}
そして、ブロックで何が起こるか:
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
_texture_draw(((mapdata[y][x] >> 4) & 1) << 2 | (mapdata[y][x] & 3), x, y);
関数「b」
「b」関数を詳しく見ると、flood_fillアルゴリズムの実装と非常によく似ていることがわかります。これは、理論上の目的と一致します。つまり、「ワイヤ」を目的の状態で「フラッディング」し、現在の波面をワイヤの端まで伝播できるようにします。名前を変更して、「本番準備完了」ブロックに配置しましょう。
フラッドフィル
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/* */
/*! \brief */
#define IMAGE_WIDTH (1220)
/*! \brief */
#define IMAGE_HEIGHT (616)
/*! \brief */
#define IMAGE_SHIFTX (580)
/*! \brief */
#define TEXTURE_COUNT (8)
/*! \brief */
#define TEXTURE_WIDTH (64)
/*! \brief */
#define TEXTURE_HEIGHT (40)
/*! \brief */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief */
#define TEXTURE_TOP_HEIGHT (32)
/*! \brief */
#define MAP_WIDTH (19)
/*! \brief */
#define MAP_HEIGHT (19)
/*! \brief -. '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief NOR- */
#define MAP_ITERATIONS (20)
/*! \brief - */
enum map_characters {
MAPCHAR_WIRE = '.', /**< (ASCII = 46) */
MAPCHAR_PLUS = '+', /**< ( ) (ASCII = 43) */
MAPCHAR_MINUS = '-', /**< ( ) (ASCII = 45) */
MAPCHAR_NOR = '>', /**< NOR- (ASCII = 62) */
};
/*! \brief .
* int */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief , */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief .
* '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];
/*! \brief Xlib */
Display * display;
/*! \brief Xlib */
Window window;
/*! \brief */
XImage * image;
/* \brief , */
static void _image_reset(void) {
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++)
pixdata[y][x] = 0;
}
/*! \brief
* \param[in] t
* \param[in] x X
* \param[in] y Y */
static void _texture_draw(int t, int x, int y) {
for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
if (textures[t][ty][tx])
pixdata[ty +
y * (TEXTURE_TOP_HEIGHT / 2) +
x * (TEXTURE_TOP_HEIGHT / 2)]
[tx +
IMAGE_SHIFTX +
x * (TEXTURE_TOP_WIDTH / 2) -
y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}
/*! \brief -
* \param[in] filename - */
static void _map_read(const char * filename) {
int f = open(filename, 0);
read(f, mapdata, MAP_FILEDATA);
close(f);
}
/*! \brief -
* */
static void _map_wire_inputs(void) {
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if ((x % 14 == 2) && (y % 4 == 3))
mapdata[y][x] = MAPCHAR_WIRE;
}
/*! \brief
* \param[in] t ,
* \param[in] x X-
* \param[in] y Y-
* \param[in] c
* \param[in] l */
static void _map_fill(int t, int x, int y, int c, int l) {
if ((x >= MAP_WIDTH || y >= MAP_HEIGHT ||
x < 0 || y < 0) || (mapdata[y][x] == l)
|| (mapdata[y][x] != c))
return;
mapdata[y][x] = l;
_map_fill(t, x - 1, y, c, l);
_map_fill(t, x + 1, y, c, l);
_map_fill(t, x, y - 1, c, l);
_map_fill(t, x, y + 1, c, l);
}
/*! \brief
* .
* \param[in] counter */
static void _map_wire_counter(int counter) {
_map_fill(0, 2, 3, mapdata[3][2], counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 7, mapdata[7][2], counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}
/*! \brief () NOR- */
static void _map_process_gates(void) {
for (int i = 0; i < MAP_ITERATIONS; i++)
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if (mapdata[y][x] == MAPCHAR_NOR)
_map_fill(0, x + 1, y, mapdata[y][x + 1],
!(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
|| mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ?
MAPCHAR_PLUS : MAPCHAR_MINUS);
}
/* */
int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
int rn = 2166136261;
void *T;
void e(int t, int x, int y, int c, int l) {
if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT ||
x < 0 || y < 0) ||
(textures[t][y][x] == l) ||
(textures[t][y][x] != c))
return;
textures[t][y][x] = l;
e(t, x - 1, y, c, l);
e(t, x + 1, y, c, l);
e(t, x, y - 1, c, l);
e(t, x, y + 1, c, l);
}
void k(int t, int x, int y, int c, int l) {
while (c--) {
textures[t][y][x++] = l;
textures[t][y++][x++] = l;
}
}
void r(int t, int x, int y, int c, int l) {
while (c--) {
textures[t][y][x--] = l;
textures[t][y++][x--] = l;
}
}
void u(int t, int x, int y, int c, int l) {
while (c--)
textures[t][y++][x] = l;
}
char *z[8] = {
(char[]) {4},
(char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
(char[]) {5, 1},
(char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
38 - 0,
4},
(char[]) {4},
(char[]) {4},
(char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
3, 30, 38 - 3, 4},
(char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
0, 8 + 0 + 0, 21, 12 - 0, 1,
31, 9 + 0, 12 - 0, 1,
55 - 0 - 0, 21, 12 - 0, 0,
32, 9 + 3, 12 - 3, 0,
8 + 3 + 3, 21, 12 - 3, 1,
31, 9 + 3, 12 - 3, 1,
55 - 3 - 3, 21, 12 - 3, 6,
14 + 0, 2, 31 + 0, 13, 4,
1 - 0, 31 + 0, 16, 7, 3,
30 + 3 * 0, 14, 6,
12 + 0 * 4, 3, 32 - 0,
11 + 0 * 8, 6, 14 + 1, 2,
31 + 1, 13, 4, 1 - 1,
31 + 1, 16, 7, 3,
30 + 3 * 1, 14, 6,
12 + 1 * 4, 3, 32 - 1,
11 + 1 * 8,
4}
};
int main(int a, char *s[]) {
display = XOpenDisplay(0);
window = XCreateSimpleWindow(display,
RootWindow(display, DefaultScreen(display)),
0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
image = XCreateImage(display,
DefaultVisual(display, DefaultScreen(display)),
DefaultDepth(display, DefaultScreen(display)),
2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
for (int i = 0; i < 8; i++) {
char *p = z[i];
int c = 0;
while (*p != 4) {
switch (*p) {
case 0:
k(i, p[1], p[2], p[3], c);
p += 4;
break;
case 1:
r(i, p[1], p[2], p[3], c);
p += 4;
break;
case 2:
u(i, p[1], p[2], p[3], c);
p += 4;
break;
case 3:
e(i, p[1]
, p[2], 0, c);
p += 3;
break;
case 5:
p = z[p[1]];
break;
case 6:
c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
p += 2;
break;
}
}
}
while (a++) {
_map_read(s[1]);
_map_wire_inputs();
_map_wire_counter(a);
_map_process_gates();
_image_reset();
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
_texture_draw(((mapdata[y][x] >> 4) & 1) << 2 | (mapdata[y][x] & 3), x, y);
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if ((x % 14 == 2) && (y % 4 == 3))
_texture_draw(7, x, y);
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++) {
pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
pixdata[y][x] += 986895 & (rn *= 16777619);
}
XPutImage(display, window,
DefaultGC(display, DefaultScreen(display)),
image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
XMapWindow(display, window);
XFlush(display);
sleep(1);
}
return 0;
}
奇妙なブロック
今、行で何が起こっているかを解析することが残っています:
_texture_draw(((mapdata[y][x] >> 4) & 1) << 2 | (mapdata[y][x] & 3), x, y);
mapdata内に含めることができる状態の完全なテーブルをすでに作成しているため、最初のパラメーターのすべての出力値を取得できます:
| enum | int | 結果 |
|---|---|---|
| MAPCHAR_WIRE | 46 | 2 |
| MAPCHAR_PLUS | 43 | 3 |
| MAPCHAR_MINUS | 45 | 1 |
| MAPCHAR_NOR | 62 | 6 |
| MAPCHAR_EMPTY | 32 | 0 |
ええ、つまり、この変換の結果として、テクスチャ配列のテクスチャインデックスを取得します。
読み取り可能で連想的に理解可能なシンボルのセットからテクスチャインデックスへの生成のメカニズムについて考えるのに数時間かかりました。ワイヤーとNOR要素を意味するシンボルを書き、それらのバイナリ値をペイントした後、一意の領域を丸で囲みました。現在のオプションに加えて、より複雑な計算を行う2番目のオプションがありましたが、それはより長いため、トークンの制限に適合しませんでした。
これにより、別の関数を分離して、各テクスチャの列挙を宣言することができます。
別のリファクタリング後:
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/* */
/*! \brief */
#define IMAGE_WIDTH (1220)
/*! \brief */
#define IMAGE_HEIGHT (616)
/*! \brief */
#define IMAGE_SHIFTX (580)
/*! \brief */
#define TEXTURE_COUNT (8)
/*! \brief */
#define TEXTURE_WIDTH (64)
/*! \brief */
#define TEXTURE_HEIGHT (40)
/*! \brief */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief */
#define TEXTURE_TOP_HEIGHT (32)
/*! \brief */
#define MAP_WIDTH (19)
/*! \brief */
#define MAP_HEIGHT (19)
/*! \brief -. '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief NOR- */
#define MAP_ITERATIONS (20)
/*! \brief - */
enum map_characters {
MAPCHAR_WIRE = '.', /**< (ASCII = 46) */
MAPCHAR_PLUS = '+', /**< ( ) (ASCII = 43) */
MAPCHAR_MINUS = '-', /**< ( ) (ASCII = 45) */
MAPCHAR_NOR = '>', /**< NOR- (ASCII = 62) */
MAPCHAR_EMPTY = ' ', /**< (ASCII = 32) */
};
/*! \brief */
enum textures_indexes {
TEXINDEX_EMPTY = (0), /**< */
TEXINDEX_MINUS = (1), /**< " " */
TEXINDEX_WIRE = (2), /**< */
TEXINDEX_PLUS = (3), /**< "" */
/**/
TEXINDEX_NOR = (6) /**< NOR- */
};
/*! \brief */
enum program_arguments {
ARG_PROGRAM, /**< */
ARG_BLUEPRINT /**< - */
};
/*! \brief .
* int */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief , */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief .
* '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];
/*! \brief Xlib */
Display * display;
/*! \brief Xlib */
Window window;
/*! \brief */
XImage * image;
/* \brief , */
static void _image_reset(void) {
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++)
pixdata[y][x] = 0;
}
/*! \brief
* \param[in] elem
* \return */
static int _map2texture(char elem) {
return ((elem >> 4) & 1) << 2 | (elem & 3);
}
/*! \brief */
static void _image_compile(void) {
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
_texture_draw(_map2texture(mapdata[y][x]), x, y);
}
/*! \brief */
static void _image_draw(void) {
XPutImage(display, window,
DefaultGC(display, DefaultScreen(display)),
image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
XMapWindow(display, window);
XFlush(display);
}
/*! \brief
* \param[in] t
* \param[in] x X
* \param[in] y Y */
static void _texture_draw(int t, int x, int y) {
for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
if (textures[t][ty][tx])
pixdata[ty +
y * (TEXTURE_TOP_HEIGHT / 2) +
x * (TEXTURE_TOP_HEIGHT / 2)]
[tx +
IMAGE_SHIFTX +
x * (TEXTURE_TOP_WIDTH / 2) -
y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}
/*! \brief -
* \param[in] filename - */
static void _map_read(const char * filename) {
int f = open(filename, 0);
read(f, mapdata, MAP_FILEDATA);
close(f);
}
/*! \brief -
* */
static void _map_wire_inputs(void) {
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if ((x % 14 == 2) && (y % 4 == 3))
mapdata[y][x] = MAPCHAR_WIRE;
}
/*! \brief
* \param[in] t ,
* \param[in] x X-
* \param[in] y Y-
* \param[in] c
* \param[in] l */
static void _map_fill(int t, int x, int y, int c, int l) {
if ((x >= MAP_WIDTH || y >= MAP_HEIGHT ||
x < 0 || y < 0) || (mapdata[y][x] == l)
|| (mapdata[y][x] != c))
return;
mapdata[y][x] = l;
_map_fill(t, x - 1, y, c, l);
_map_fill(t, x + 1, y, c, l);
_map_fill(t, x, y - 1, c, l);
_map_fill(t, x, y + 1, c, l);
}
/*! \brief
* .
* \param[in] counter */
static void _map_wire_counter(int counter) {
_map_fill(0, 2, 3, mapdata[3][2], counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 7, mapdata[7][2], counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}
/*! \brief () NOR- */
static void _map_process_gates(void) {
for (int i = 0; i < MAP_ITERATIONS; i++)
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if (mapdata[y][x] == MAPCHAR_NOR)
_map_fill(0, x + 1, y, mapdata[y][x + 1],
!(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
|| mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ?
MAPCHAR_PLUS : MAPCHAR_MINUS);
}
/* */
int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
int rn = 2166136261;
void *T;
void e(int t, int x, int y, int c, int l) {
if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT ||
x < 0 || y < 0) ||
(textures[t][y][x] == l) ||
(textures[t][y][x] != c))
return;
textures[t][y][x] = l;
e(t, x - 1, y, c, l);
e(t, x + 1, y, c, l);
e(t, x, y - 1, c, l);
e(t, x, y + 1, c, l);
}
void k(int t, int x, int y, int c, int l) {
while (c--) {
textures[t][y][x++] = l;
textures[t][y++][x++] = l;
}
}
void r(int t, int x, int y, int c, int l) {
while (c--) {
textures[t][y][x--] = l;
textures[t][y++][x--] = l;
}
}
void u(int t, int x, int y, int c, int l) {
while (c--)
textures[t][y++][x] = l;
}
char *z[8] = {
(char[]) {4},
(char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
(char[]) {5, 1},
(char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
38 - 0,
4},
(char[]) {4},
(char[]) {4},
(char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
3, 30, 38 - 3, 4},
(char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
0, 8 + 0 + 0, 21, 12 - 0, 1,
31, 9 + 0, 12 - 0, 1,
55 - 0 - 0, 21, 12 - 0, 0,
32, 9 + 3, 12 - 3, 0,
8 + 3 + 3, 21, 12 - 3, 1,
31, 9 + 3, 12 - 3, 1,
55 - 3 - 3, 21, 12 - 3, 6,
14 + 0, 2, 31 + 0, 13, 4,
1 - 0, 31 + 0, 16, 7, 3,
30 + 3 * 0, 14, 6,
12 + 0 * 4, 3, 32 - 0,
11 + 0 * 8, 6, 14 + 1, 2,
31 + 1, 13, 4, 1 - 1,
31 + 1, 16, 7, 3,
30 + 3 * 1, 14, 6,
12 + 1 * 4, 3, 32 - 1,
11 + 1 * 8,
4}
};
int main(int argc, char * args[]) {
display = XOpenDisplay(0);
window = XCreateSimpleWindow(display,
RootWindow(display, DefaultScreen(display)),
0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
image = XCreateImage(display,
DefaultVisual(display, DefaultScreen(display)),
DefaultDepth(display, DefaultScreen(display)),
2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
for (int i = 0; i < 8; i++) {
char *p = z[i];
int c = 0;
while (*p != 4) {
switch (*p) {
case 0:
k(i, p[1], p[2], p[3], c);
p += 4;
break;
case 1:
r(i, p[1], p[2], p[3], c);
p += 4;
break;
case 2:
u(i, p[1], p[2], p[3], c);
p += 4;
break;
case 3:
e(i, p[1]
, p[2], 0, c);
p += 3;
break;
case 5:
p = z[p[1]];
break;
case 6:
c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
p += 2;
break;
}
}
}
unsigned int counter = 0;
while (counter++) {
_map_read(args[ARG_BLUEPRINT]);
_map_wire_inputs();
_map_wire_counter(counter);
_map_process_gates();
_image_reset();
_image_compile();
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if ((x % 14 == 2) && (y % 4 == 3))
_texture_draw(7, x, y);
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++) {
pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
pixdata[y][x] += 986895 & (rn *= 16777619);
}
_image_draw();
sleep(1);
}
return 0;
}
テクスチャ#7
「z」配列をよく見ると、テクスチャ数の定数として8つのデータブロックが含まれていることがわかります。また、列挙の場合と同様に、位置4と5に2つのスペースがあります。おそらく、これはテクスチャデータです。ただし、8つの画像が含まれており、7つしか「開く」ことができませんでした。ただし、十分に注意すると、7番目のテクスチャを具体的に描画するコードが存在することがわかります。
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if ((x % 14 == 2) && (y % 4 == 3))
_texture_draw(7, x, y);
位置によって、それが何であるかはすでに推測できますが、これらの行をコメントアウトしてアプリケーションを実行しましょう。
前:
後:
これがボード上の穴のテクスチャであることが確実にわかり、別の関数でレンダリングすることで列挙リストに追加できます。
組み立てられたすべてのテクスチャ:
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/* */
/*! \brief */
#define IMAGE_WIDTH (1220)
/*! \brief */
#define IMAGE_HEIGHT (616)
/*! \brief */
#define IMAGE_SHIFTX (580)
/*! \brief */
#define TEXTURE_COUNT (8)
/*! \brief */
#define TEXTURE_WIDTH (64)
/*! \brief */
#define TEXTURE_HEIGHT (40)
/*! \brief */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief */
#define TEXTURE_TOP_HEIGHT (32)
/*! \brief */
#define MAP_WIDTH (19)
/*! \brief */
#define MAP_HEIGHT (19)
/*! \brief -. '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief NOR- */
#define MAP_ITERATIONS (20)
/*! \brief - */
enum map_characters {
MAPCHAR_WIRE = '.', /**< (ASCII = 46) */
MAPCHAR_PLUS = '+', /**< ( ) (ASCII = 43) */
MAPCHAR_MINUS = '-', /**< ( ) (ASCII = 45) */
MAPCHAR_NOR = '>', /**< NOR- (ASCII = 62) */
MAPCHAR_EMPTY = ' ', /**< (ASCII = 32) */
};
/*! \brief */
enum textures_indexes {
TEXINDEX_EMPTY = (0), /**< */
TEXINDEX_MINUS = (1), /**< " " */
TEXINDEX_WIRE = (2), /**< */
TEXINDEX_PLUS = (3), /**< "" */
/**/
TEXINDEX_NOR = (6), /**< NOR- */
TEXINDEX_HOLE = (7) /**< */
};
/*! \brief */
enum program_arguments {
ARG_PROGRAM, /**< */
ARG_BLUEPRINT /**< - */
};
/*! \brief .
* int */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief , */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief .
* '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];
/*! \brief Xlib */
Display * display;
/*! \brief Xlib */
Window window;
/*! \brief */
XImage * image;
static void _texture_draw(int t, int x, int y);
/*! \brief */
static void _image_create(void) {
display = XOpenDisplay(0);
window = XCreateSimpleWindow(display,
RootWindow(display, DefaultScreen(display)),
0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
image = XCreateImage(display,
DefaultVisual(display, DefaultScreen(display)),
DefaultDepth(display, DefaultScreen(display)),
2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
}
/* \brief , */
static void _image_reset(void) {
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++)
pixdata[y][x] = 0;
}
/*! \brief
* \param[in] elem
* \return */
static int _map2texture(char elem) {
return ((elem >> 4) & 1) << 2 | (elem & 3);
}
/*! \brief */
static void _image_compile(void) {
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
_texture_draw(_map2texture(mapdata[y][x]), x, y);
}
/*! \brief */
static void _image_draw(void) {
XPutImage(display, window,
DefaultGC(display, DefaultScreen(display)),
image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
XMapWindow(display, window);
XFlush(display);
}
/*! \brief */
static void _image_drill(void) {
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if ((x % 14 == 2) && (y % 4 == 3))
_texture_draw(TEXINDEX_HOLE, x, y);
}
/*! \brief
* \param[in] t
* \param[in] x X
* \param[in] y Y */
static void _texture_draw(int t, int x, int y) {
for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
if (textures[t][ty][tx])
pixdata[ty +
y * (TEXTURE_TOP_HEIGHT / 2) +
x * (TEXTURE_TOP_HEIGHT / 2)]
[tx +
IMAGE_SHIFTX +
x * (TEXTURE_TOP_WIDTH / 2) -
y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}
/*! \brief -
* \param[in] filename - */
static void _map_read(const char * filename) {
int f = open(filename, 0);
read(f, mapdata, MAP_FILEDATA);
close(f);
}
/*! \brief -
* */
static void _map_wire_inputs(void) {
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if ((x % 14 == 2) && (y % 4 == 3))
mapdata[y][x] = MAPCHAR_WIRE;
}
/*! \brief
* \param[in] t ,
* \param[in] x X-
* \param[in] y Y-
* \param[in] c
* \param[in] l */
static void _map_fill(int t, int x, int y, int c, int l) {
if ((x >= MAP_WIDTH || y >= MAP_HEIGHT ||
x < 0 || y < 0) || (mapdata[y][x] == l)
|| (mapdata[y][x] != c))
return;
mapdata[y][x] = l;
_map_fill(t, x - 1, y, c, l);
_map_fill(t, x + 1, y, c, l);
_map_fill(t, x, y - 1, c, l);
_map_fill(t, x, y + 1, c, l);
}
/*! \brief
* .
* \param[in] counter */
static void _map_wire_counter(int counter) {
_map_fill(0, 2, 3, mapdata[3][2], counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 7, mapdata[7][2], counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}
/*! \brief () NOR- */
static void _map_process_gates(void) {
for (int i = 0; i < MAP_ITERATIONS; i++)
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if (mapdata[y][x] == MAPCHAR_NOR)
_map_fill(0, x + 1, y, mapdata[y][x + 1],
!(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
|| mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ?
MAPCHAR_PLUS : MAPCHAR_MINUS);
}
/* */
int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
int rn = 2166136261;
void *T;
void e(int t, int x, int y, int c, int l) {
if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT ||
x < 0 || y < 0) ||
(textures[t][y][x] == l) ||
(textures[t][y][x] != c))
return;
textures[t][y][x] = l;
e(t, x - 1, y, c, l);
e(t, x + 1, y, c, l);
e(t, x, y - 1, c, l);
e(t, x, y + 1, c, l);
}
void k(int t, int x, int y, int c, int l) {
while (c--) {
textures[t][y][x++] = l;
textures[t][y++][x++] = l;
}
}
void r(int t, int x, int y, int c, int l) {
while (c--) {
textures[t][y][x--] = l;
textures[t][y++][x--] = l;
}
}
void u(int t, int x, int y, int c, int l) {
while (c--)
textures[t][y++][x] = l;
}
char *z[8] = {
(char[]) {4},
(char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
(char[]) {5, 1},
(char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
38 - 0,
4},
(char[]) {4},
(char[]) {4},
(char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
3, 30, 38 - 3, 4},
(char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
0, 8 + 0 + 0, 21, 12 - 0, 1,
31, 9 + 0, 12 - 0, 1,
55 - 0 - 0, 21, 12 - 0, 0,
32, 9 + 3, 12 - 3, 0,
8 + 3 + 3, 21, 12 - 3, 1,
31, 9 + 3, 12 - 3, 1,
55 - 3 - 3, 21, 12 - 3, 6,
14 + 0, 2, 31 + 0, 13, 4,
1 - 0, 31 + 0, 16, 7, 3,
30 + 3 * 0, 14, 6,
12 + 0 * 4, 3, 32 - 0,
11 + 0 * 8, 6, 14 + 1, 2,
31 + 1, 13, 4, 1 - 1,
31 + 1, 16, 7, 3,
30 + 3 * 1, 14, 6,
12 + 1 * 4, 3, 32 - 1,
11 + 1 * 8,
4}
};
int main(int argc, char * args[]) {
_image_create();
for (int i = 0; i < 8; i++) {
char *p = z[i];
int c = 0;
while (*p != 4) {
switch (*p) {
case 0:
k(i, p[1], p[2], p[3], c);
p += 4;
break;
case 1:
r(i, p[1], p[2], p[3], c);
p += 4;
break;
case 2:
u(i, p[1], p[2], p[3], c);
p += 4;
break;
case 3:
e(i, p[1]
, p[2], 0, c);
p += 3;
break;
case 5:
p = z[p[1]];
break;
case 6:
c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
p += 2;
break;
}
}
}
unsigned int counter = 1;
while (counter++) {
_map_read(args[ARG_BLUEPRINT]);
_map_wire_inputs();
_map_wire_counter(counter);
_map_process_gates();
_image_reset();
_image_compile();
_image_drill();
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++) {
pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
pixdata[y][x] += 986895 & (rn *= 16777619);
}
_image_draw();
sleep(1);
}
return 0;
}
シェーダー
前回の記事の猫はシェーダーを約束しました。そして、彼らはここにいます。そして、それらの処理を担当するコードはどこにありますか?
_image_reset(); //
_image_compile(); //
_image_drill(); //
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++) {
pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
pixdata[y][x] += 986895 & (rn *= 16777619);
}
_image_draw(); //
除去の方法により、画面のノイズとLCDモニターの効果がこれらの2つの線を与えることがわかります。それらはどのように機能しますか?
最後のものから始めましょう:
pixdata[y][x] += 986895 & (rn *= 16777619);
各ピクセルに値986895(16進バージョンでは0x0f0f0fのように見えます)が追加されます。これは、以前はビットAND演算と、rnに16777619を掛けた結果を組み合わせたものでした。各チャネルの16グラデーション以内の画面上。そして、ノイズが現れるので、rnはランダム数ジェネレータです。しかし、これはどのように達成されますか?
int rn = 2166136261;
プログラムの最初の段階で、rn変数は番号2166136261で初期化されます。また、各反復で、ピクセルに16777619が乗算されます。これは疑似乱数ジェネレーターにすぎません。ただし、十分に研究された線形ジェネレータの代わりに、XORステップのないFNVハッシュアルゴリズムが使用されます。これは、最終結果が必要ないためです。
前の行がどのように機能するかはまだわかりません。
pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
1バイトの光チャネル0xe0e0e0を使用しているため、番号14737632を16進形式に変換してみましょう。そして今、xを0から3に等しくして、対応する計算を実行します。
0xe0e0e0 | (31 << ((0 % 3) << 3)) = e0e0ff
0xe0e0e0 | (31 << ((1 % 3) << 3)) = e0ffe0
0xe0e0e0 | (31 << ((2 % 3) << 3)) = ffe0e0
これらのマスクが「&」操作を使用してピクセルの色に適用されると、それぞれミュートされたRおよびG、RおよびB、GおよびBチャネルが得られます。これは、LCDモニターの効果のように見えます。
それらを別々の関数に分けましょう:
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/* */
/*! \brief */
#define IMAGE_WIDTH (1220)
/*! \brief */
#define IMAGE_HEIGHT (616)
/*! \brief */
#define IMAGE_SHIFTX (580)
/*! \brief */
#define TEXTURE_COUNT (8)
/*! \brief */
#define TEXTURE_WIDTH (64)
/*! \brief */
#define TEXTURE_HEIGHT (40)
/*! \brief */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief */
#define TEXTURE_TOP_HEIGHT (32)
/*! \brief */
#define MAP_WIDTH (19)
/*! \brief */
#define MAP_HEIGHT (19)
/*! \brief -. '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief NOR- */
#define MAP_ITERATIONS (20)
/*! \brief - */
enum map_characters {
MAPCHAR_WIRE = '.', /**< (ASCII = 46) */
MAPCHAR_PLUS = '+', /**< ( ) (ASCII = 43) */
MAPCHAR_MINUS = '-', /**< ( ) (ASCII = 45) */
MAPCHAR_NOR = '>', /**< NOR- (ASCII = 62) */
MAPCHAR_EMPTY = ' ', /**< (ASCII = 32) */
};
/*! \brief */
enum textures_indexes {
TEXINDEX_EMPTY = (0), /**< */
TEXINDEX_MINUS = (1), /**< " " */
TEXINDEX_WIRE = (2), /**< */
TEXINDEX_PLUS = (3), /**< "" */
/**/
TEXINDEX_NOR = (6), /**< NOR- */
TEXINDEX_HOLE = (7) /**< */
};
/*! \brief */
enum program_arguments {
ARG_PROGRAM, /**< */
ARG_BLUEPRINT /**< - */
};
/*! \brief .
* int */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief , */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief .
* '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];
/*! \brief */
int random = 2166136261;
/*! \brief Xlib */
Display * display;
/*! \brief Xlib */
Window window;
/*! \brief */
XImage * image;
static void _texture_draw(int t, int x, int y);
/*! \brief */
static void _image_create(void) {
display = XOpenDisplay(0);
window = XCreateSimpleWindow(display,
RootWindow(display, DefaultScreen(display)),
0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
image = XCreateImage(display,
DefaultVisual(display, DefaultScreen(display)),
DefaultDepth(display, DefaultScreen(display)),
2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
}
/* \brief , */
static void _image_reset(void) {
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++)
pixdata[y][x] = 0;
}
/*! \brief
* \param[in] elem
* \return */
static int _map2texture(char elem) {
return ((elem >> 4) & 1) << 2 | (elem & 3);
}
/*! \brief */
static void _image_compile(void) {
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
_texture_draw(_map2texture(mapdata[y][x]), x, y);
}
/*! \brief */
static void _image_draw(void) {
XPutImage(display, window,
DefaultGC(display, DefaultScreen(display)),
image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
XMapWindow(display, window);
XFlush(display);
}
/*! \brief */
static void _image_drill(void) {
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if ((x % 14 == 2) && (y % 4 == 3))
_texture_draw(TEXINDEX_HOLE, x, y);
}
/*! \brief LCD-
* \param[in] x X-
* \param[in] y Y- */
static void _shader_lcd(int x, int y) {
pixdata[y][x] &= 0xe0e0e0 | (31 << ((x % 3) << 3));
}
/*! \brief
* \param[in] x X-
* \param[in] y Y- */
static void _shader_noise(int x, int y) {
pixdata[y][x] += 0x0f0f0f & (random *= 16777619);
}
/*! \brief */
static void _image_postprocess(void) {
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++) {
_shader_lcd(x, y);
_shader_noise(x, y);
}
}
/*! \brief
* \param[in] t
* \param[in] x X
* \param[in] y Y */
static void _texture_draw(int t, int x, int y) {
for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
if (textures[t][ty][tx])
pixdata[ty +
y * (TEXTURE_TOP_HEIGHT / 2) +
x * (TEXTURE_TOP_HEIGHT / 2)]
[tx +
IMAGE_SHIFTX +
x * (TEXTURE_TOP_WIDTH / 2) -
y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}
/*! \brief -
* \param[in] filename - */
static void _map_read(const char * filename) {
int f = open(filename, 0);
read(f, mapdata, MAP_FILEDATA);
close(f);
}
/*! \brief -
* */
static void _map_wire_inputs(void) {
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if ((x % 14 == 2) && (y % 4 == 3))
mapdata[y][x] = MAPCHAR_WIRE;
}
/*! \brief
* \param[in] t ,
* \param[in] x X-
* \param[in] y Y-
* \param[in] c
* \param[in] l */
static void _map_fill(int t, int x, int y, int c, int l) {
if ((x >= MAP_WIDTH || y >= MAP_HEIGHT ||
x < 0 || y < 0) || (mapdata[y][x] == l)
|| (mapdata[y][x] != c))
return;
mapdata[y][x] = l;
_map_fill(t, x - 1, y, c, l);
_map_fill(t, x + 1, y, c, l);
_map_fill(t, x, y - 1, c, l);
_map_fill(t, x, y + 1, c, l);
}
/*! \brief
* .
* \param[in] counter */
static void _map_wire_counter(int counter) {
_map_fill(0, 2, 3, mapdata[3][2], counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 7, mapdata[7][2], counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}
/*! \brief () NOR- */
static void _map_process_gates(void) {
for (int i = 0; i < MAP_ITERATIONS; i++)
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if (mapdata[y][x] == MAPCHAR_NOR)
_map_fill(0, x + 1, y, mapdata[y][x + 1],
!(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
|| mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ?
MAPCHAR_PLUS : MAPCHAR_MINUS);
}
/* */
int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
void e(int t, int x, int y, int c, int l) {
if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT ||
x < 0 || y < 0) ||
(textures[t][y][x] == l) ||
(textures[t][y][x] != c))
return;
textures[t][y][x] = l;
e(t, x - 1, y, c, l);
e(t, x + 1, y, c, l);
e(t, x, y - 1, c, l);
e(t, x, y + 1, c, l);
}
void k(int t, int x, int y, int c, int l) {
while (c--) {
textures[t][y][x++] = l;
textures[t][y++][x++] = l;
}
}
void r(int t, int x, int y, int c, int l) {
while (c--) {
textures[t][y][x--] = l;
textures[t][y++][x--] = l;
}
}
void u(int t, int x, int y, int c, int l) {
while (c--)
textures[t][y++][x] = l;
}
char *z[8] = {
(char[]) {4},
(char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
(char[]) {5, 1},
(char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
38 - 0,
4},
(char[]) {4},
(char[]) {4},
(char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
3, 30, 38 - 3, 4},
(char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
0, 8 + 0 + 0, 21, 12 - 0, 1,
31, 9 + 0, 12 - 0, 1,
55 - 0 - 0, 21, 12 - 0, 0,
32, 9 + 3, 12 - 3, 0,
8 + 3 + 3, 21, 12 - 3, 1,
31, 9 + 3, 12 - 3, 1,
55 - 3 - 3, 21, 12 - 3, 6,
14 + 0, 2, 31 + 0, 13, 4,
1 - 0, 31 + 0, 16, 7, 3,
30 + 3 * 0, 14, 6,
12 + 0 * 4, 3, 32 - 0,
11 + 0 * 8, 6, 14 + 1, 2,
31 + 1, 13, 4, 1 - 1,
31 + 1, 16, 7, 3,
30 + 3 * 1, 14, 6,
12 + 1 * 4, 3, 32 - 1,
11 + 1 * 8,
4}
};
int main(int argc, char * args[]) {
_image_create();
for (int i = 0; i < 8; i++) {
char *p = z[i];
int c = 0;
while (*p != 4) {
switch (*p) {
case 0:
k(i, p[1], p[2], p[3], c);
p += 4;
break;
case 1:
r(i, p[1], p[2], p[3], c);
p += 4;
break;
case 2:
u(i, p[1], p[2], p[3], c);
p += 4;
break;
case 3:
e(i, p[1]
, p[2], 0, c);
p += 3;
break;
case 5:
p = z[p[1]];
break;
case 6:
c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
p += 2;
break;
}
}
}
unsigned int counter = 1;
while (counter++) {
_map_read(args[ARG_BLUEPRINT]);
_map_wire_inputs();
_map_wire_counter(counter);
_map_process_gates();
_image_reset();
_image_compile();
_image_drill();
_image_postprocess();
_image_draw();
sleep(1);
}
return 0;
}
「E」、「k」、「r」、「u」
まだ調査も名前も変更していない4つの関数があります。これらは、「e」、「k」、「r」、「u」です。それらが呼び出される場所を探すことなく、それらを検査してみましょう。
void e(int t, int x, int y, int c, int l) {
if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT ||
x < 0 || y < 0) ||
(textures[t][y][x] == l) ||
(textures[t][y][x] != c))
return;
textures[t][y][x] = l;
e(t, x - 1, y, c, l);
e(t, x + 1, y, c, l);
e(t, x, y - 1, c, l);
e(t, x, y + 1, c, l);
}
明らかに、この関数は、textures配列に対してのみ、flood_fillのように見え、機能します。名前を_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;
}
}
与えられた各ユニットcの関数 "k"と "r"は、値lで2つのピクセルを描画し、左右に2ピクセル、下に1つ移動します。これは、これらが等尺性の線SWとSEを描画するための関数であることを意味します。それらの名前を_texture_lineswと_texture_lineseに変更しましょう。
この時点で、最後の関数「u」が垂直に下向きに線を引くことはすでに推測できます。
void u(int t, int x, int y, int c, int l) {
while (c--)
textures[t][y++][x] = l;
}
名前を_texture_linedownに変更しましょう。
個々の機能はすべてリファクタリングされています。
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/* */
/*! \brief */
#define IMAGE_WIDTH (1220)
/*! \brief */
#define IMAGE_HEIGHT (616)
/*! \brief */
#define IMAGE_SHIFTX (580)
/*! \brief */
#define TEXTURE_COUNT (8)
/*! \brief */
#define TEXTURE_WIDTH (64)
/*! \brief */
#define TEXTURE_HEIGHT (40)
/*! \brief */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief */
#define TEXTURE_TOP_HEIGHT (32)
/*! \brief */
#define MAP_WIDTH (19)
/*! \brief */
#define MAP_HEIGHT (19)
/*! \brief -. '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief NOR- */
#define MAP_ITERATIONS (20)
/*! \brief - */
enum map_characters {
MAPCHAR_WIRE = '.', /**< (ASCII = 46) */
MAPCHAR_PLUS = '+', /**< ( ) (ASCII = 43) */
MAPCHAR_MINUS = '-', /**< ( ) (ASCII = 45) */
MAPCHAR_NOR = '>', /**< NOR- (ASCII = 62) */
MAPCHAR_EMPTY = ' ', /**< (ASCII = 32) */
};
/*! \brief */
enum textures_indexes {
TEXINDEX_EMPTY = (0), /**< */
TEXINDEX_MINUS = (1), /**< " " */
TEXINDEX_WIRE = (2), /**< */
TEXINDEX_PLUS = (3), /**< "" */
/**/
TEXINDEX_NOR = (6), /**< NOR- */
TEXINDEX_HOLE = (7) /**< */
};
/*! \brief */
enum program_arguments {
ARG_PROGRAM, /**< */
ARG_BLUEPRINT /**< - */
};
/*! \brief .
* int */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief , */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief .
* '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];
/*! \brief */
int random = 2166136261;
/*! \brief Xlib */
Display * display;
/*! \brief Xlib */
Window window;
/*! \brief */
XImage * image;
static void _texture_draw(int t, int x, int y);
/*! \brief */
static void _image_create(void) {
display = XOpenDisplay(0);
window = XCreateSimpleWindow(display,
RootWindow(display, DefaultScreen(display)),
0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
image = XCreateImage(display,
DefaultVisual(display, DefaultScreen(display)),
DefaultDepth(display, DefaultScreen(display)),
2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
}
/* \brief , */
static void _image_reset(void) {
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++)
pixdata[y][x] = 0;
}
/*! \brief
* \param[in] elem
* \return */
static int _map2texture(char elem) {
return ((elem >> 4) & 1) << 2 | (elem & 3);
}
/*! \brief */
static void _image_compile(void) {
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
_texture_draw(_map2texture(mapdata[y][x]), x, y);
}
/*! \brief */
static void _image_draw(void) {
XPutImage(display, window,
DefaultGC(display, DefaultScreen(display)),
image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
XMapWindow(display, window);
XFlush(display);
}
/*! \brief */
static void _image_drill(void) {
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if ((x % 14 == 2) && (y % 4 == 3))
_texture_draw(TEXINDEX_HOLE, x, y);
}
/*! \brief LCD-
* \param[in] x X-
* \param[in] y Y- */
static void _shader_lcd(int x, int y) {
pixdata[y][x] &= 0xe0e0e0 | (31 << ((x % 3) << 3));
}
/*! \brief
* \param[in] x X-
* \param[in] y Y- */
static void _shader_noise(int x, int y) {
pixdata[y][x] += 0x0f0f0f & (random *= 16777619);
}
/*! \brief */
static void _image_postprocess(void) {
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++) {
_shader_lcd(x, y);
_shader_noise(x, y);
}
}
/*! \brief
* \param[in] t
* \param[in] x X
* \param[in] y Y */
static void _texture_draw(int t, int x, int y) {
for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
if (textures[t][ty][tx])
pixdata[ty +
y * (TEXTURE_TOP_HEIGHT / 2) +
x * (TEXTURE_TOP_HEIGHT / 2)]
[tx +
IMAGE_SHIFTX +
x * (TEXTURE_TOP_WIDTH / 2) -
y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}
/*! \brief
* \param[in] t
* \param[in] x X-
* \param[in] y Y-
* \param[in] source
* \param[in] target */
static void _texture_fill(int t, int x, int y, int source, int target) {
if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT ||
x < 0 || y < 0) ||
(textures[t][y][x] == target) ||
(textures[t][y][x] != source))
return;
textures[t][y][x] = target;
_texture_fill(t, x - 1, y, source, target);
_texture_fill(t, x + 1, y, source, target);
_texture_fill(t, x, y - 1, source, target);
_texture_fill(t, x, y + 1, source, target);
}
/*! \brief SE
* \param[in] t
* \param[in] x X-
* \param[in] y Y-
* \param[in] c
* \param[in] color */
static void _texture_linese(int t, int x, int y, int c, int color) {
while (c--) {
textures[t][y][x++] = color;
textures[t][y++][x++] = color;
}
}
/*! \brief SW
* \param[in] t
* \param[in] x X-
* \param[in] y Y-
* \param[in] c
* \param[in] color */
static void _texture_linesw(int t, int x, int y, int c, int color) {
while (c--) {
textures[t][y][x--] = color;
textures[t][y++][x--] = color;
}
}
/*! \brief
* \param[in] t
* \param[in] x X-
* \param[in] y Y-
* \param[in] c
* \param[in] color */
static void _texture_linedown(int t, int x, int y, int c, int color) {
while (c--)
textures[t][y++][x] = color;
}
/*! \brief -
* \param[in] filename - */
static void _map_read(const char * filename) {
int f = open(filename, 0);
read(f, mapdata, MAP_FILEDATA);
close(f);
}
/*! \brief -
* */
static void _map_wire_inputs(void) {
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if ((x % 14 == 2) && (y % 4 == 3))
mapdata[y][x] = MAPCHAR_WIRE;
}
/*! \brief
* \param[in] t ,
* \param[in] x X-
* \param[in] y Y-
* \param[in] c
* \param[in] l */
static void _map_fill(int t, int x, int y, int c, int l) {
if ((x >= MAP_WIDTH || y >= MAP_HEIGHT ||
x < 0 || y < 0) || (mapdata[y][x] == l)
|| (mapdata[y][x] != c))
return;
mapdata[y][x] = l;
_map_fill(t, x - 1, y, c, l);
_map_fill(t, x + 1, y, c, l);
_map_fill(t, x, y - 1, c, l);
_map_fill(t, x, y + 1, c, l);
}
/*! \brief
* .
* \param[in] counter */
static void _map_wire_counter(int counter) {
_map_fill(0, 2, 3, mapdata[3][2], counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 7, mapdata[7][2], counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}
/*! \brief () NOR- */
static void _map_process_gates(void) {
for (int i = 0; i < MAP_ITERATIONS; i++)
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if (mapdata[y][x] == MAPCHAR_NOR)
_map_fill(0, x + 1, y, mapdata[y][x + 1],
!(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
|| mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ?
MAPCHAR_PLUS : MAPCHAR_MINUS);
}
/* */
int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
char *z[8] = {
(char[]) {4},
(char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
(char[]) {5, 1},
(char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
38 - 0,
4},
(char[]) {4},
(char[]) {4},
(char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
3, 30, 38 - 3, 4},
(char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
0, 8 + 0 + 0, 21, 12 - 0, 1,
31, 9 + 0, 12 - 0, 1,
55 - 0 - 0, 21, 12 - 0, 0,
32, 9 + 3, 12 - 3, 0,
8 + 3 + 3, 21, 12 - 3, 1,
31, 9 + 3, 12 - 3, 1,
55 - 3 - 3, 21, 12 - 3, 6,
14 + 0, 2, 31 + 0, 13, 4,
1 - 0, 31 + 0, 16, 7, 3,
30 + 3 * 0, 14, 6,
12 + 0 * 4, 3, 32 - 0,
11 + 0 * 8, 6, 14 + 1, 2,
31 + 1, 13, 4, 1 - 1,
31 + 1, 16, 7, 3,
30 + 3 * 1, 14, 6,
12 + 1 * 4, 3, 32 - 1,
11 + 1 * 8,
4}
};
int main(int argc, char * args[]) {
_image_create();
for (int i = 0; i < 8; i++) {
char *p = z[i];
int c = 0;
while (*p != 4) {
switch (*p) {
case 0:
_texture_linese(i, p[1], p[2], p[3], c);
p += 4;
break;
case 1:
_texture_linesw(i, p[1], p[2], p[3], c);
p += 4;
break;
case 2:
_texture_linedown(i, p[1], p[2], p[3], c);
p += 4;
break;
case 3:
_texture_fill(i, p[1], p[2], 0, c);
p += 3;
break;
case 5:
p = z[p[1]];
break;
case 6:
c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
p += 2;
break;
}
}
}
unsigned int counter = 1;
while (counter++) {
_map_read(args[ARG_BLUEPRINT]);
_map_wire_inputs();
_map_wire_counter(counter);
_map_process_gates();
_image_reset();
_image_compile();
_image_drill();
_image_postprocess();
_image_draw();
sleep(1);
}
return 0;
}
ベクトルグラフィックス
残りの最後のステップは1つだけです-最後のスイッチで何が起こるかを理解するために-後で残されたケース:
for (int i = 0; i < 8; i++) {
char *p = z[i];
int c = 0;
while (*p != 4) {
switch (*p) {
case 0:
_texture_linese(i, p[1], p[2], p[3], c);
p += 4;
break;
case 1:
_texture_linesw(i, p[1], p[2], p[3], c);
p += 4;
break;
case 2:
_texture_linedown(i, p[1], p[2], p[3], c);
p += 4;
break;
case 3:
_texture_fill(i, p[1], p[2], 0, c);
p += 3;
break;
case 5:
p = z[p[1]];
break;
case 6:
c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
p += 2;
break;
}
}
}
関数に新しいわかりやすい名前が付けられたので、このコードブロックは、配列 "z"からのデータを解釈し、それに含まれる指示に従って(たとえば、0、5、5、8、2- "線を南に引く-東、[5,5]から、短辺の長さが8ピクセル、色番号が2 ")で、テクスチャのセット全体が描画されます。
すべてがはっきりしているように見えますが、プログラムの色の単一の表示は気づかれませんでした。
c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
そうです、_x配列はパレットですが、非常に奇妙な「圧縮された」形式です。
int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
パレットで使用されている色の数がまだわからないため(色を設定するとき、インデックスは少なくとも4で割り切れます)、描画用にデータテーブルを再フォーマットし、カテゴリごとに番号をグループ化して、命令の署名を定数に置き換えます。
ベクトル命令テーブルのリファクタリング
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/* */
/*! \brief */
#define IMAGE_WIDTH (1220)
/*! \brief */
#define IMAGE_HEIGHT (616)
/*! \brief */
#define IMAGE_SHIFTX (580)
/*! \brief */
#define TEXTURE_COUNT (8)
/*! \brief */
#define TEXTURE_WIDTH (64)
/*! \brief */
#define TEXTURE_HEIGHT (40)
/*! \brief */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief */
#define TEXTURE_TOP_HEIGHT (32)
/*! \brief */
#define MAP_WIDTH (19)
/*! \brief */
#define MAP_HEIGHT (19)
/*! \brief -. '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief NOR- */
#define MAP_ITERATIONS (20)
/*! \brief - */
enum map_characters {
MAPCHAR_WIRE = '.', /**< (ASCII = 46) */
MAPCHAR_PLUS = '+', /**< ( ) (ASCII = 43) */
MAPCHAR_MINUS = '-', /**< ( ) (ASCII = 45) */
MAPCHAR_NOR = '>', /**< NOR- (ASCII = 62) */
MAPCHAR_EMPTY = ' ', /**< (ASCII = 32) */
};
/*! \brief */
enum textures_indexes {
TEXINDEX_EMPTY = (0), /**< */
TEXINDEX_MINUS = (1), /**< " " */
TEXINDEX_WIRE = (2), /**< */
TEXINDEX_PLUS = (3), /**< "" */
/**/
TEXINDEX_NOR = (6), /**< NOR- */
TEXINDEX_HOLE = (7) /**< */
};
/*! \brief */
enum textures_instructions {
TEXVEC_LINESE = (0), /**< SE */
TEXVEC_LINESW = (1), /**< SW */
TEXVEC_LINEDW = (2), /**< */
TEXVEC_FILL = (3), /**< */
TEXVEC_EXIT = (4), /**< */
TEXVEC_REPEAT = (5), /**< */
TEXVEC_COLOR = (6) /**< */
};
/*! \brief */
enum program_arguments {
ARG_PROGRAM, /**< */
ARG_BLUEPRINT /**< - */
};
/*! \brief .
* int */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief , */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief .
* '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];
/*! \brief */
int random = 2166136261;
/*! \brief Xlib */
Display * display;
/*! \brief Xlib */
Window window;
/*! \brief */
XImage * image;
/*! \brief */
static const char * vecdata[TEXTURE_COUNT] = {
/* TEXINDEX_EMPTY */
(char[]) { TEXVEC_EXIT },
/* TEXINDEX_MINUS */
(char[]) { TEXVEC_COLOR, 5, TEXVEC_LINESE, 32, 5, 16,
TEXVEC_LINESE, 0, 21, 16, TEXVEC_LINESW, 63, 21, 16,
TEXVEC_LINEDW, 0, 21, 4, TEXVEC_LINEDW, 31, 36, 4,
TEXVEC_LINESW, 31, 5, 16, TEXVEC_LINESE, 0, 24, 16,
TEXVEC_LINESW, 63, 24, 16, TEXVEC_LINEDW, 63, 21, 4,
TEXVEC_LINEDW, 32, 36, 4, TEXVEC_COLOR, 4,
TEXVEC_FILL, 31, 8, TEXVEC_COLOR, 6,
TEXVEC_FILL, 33, 38, TEXVEC_COLOR, 7,
TEXVEC_FILL, 30, 38, TEXVEC_EXIT },
/* TEXINDEX_WIRE */
(char[]) { TEXVEC_REPEAT, 1 },
/* TEXINDEX_PLUS */
(char[]) { TEXVEC_COLOR, 1, TEXVEC_LINESE, 32, 5, 16,
TEXVEC_LINESE, 0, 21, 16, TEXVEC_LINESW, 63, 21, 16,
TEXVEC_LINEDW, 63, 21, 4, TEXVEC_LINEDW, 31, 36, 4,
TEXVEC_LINESW, 31, 5, 16, TEXVEC_LINESE, 0, 24, 16,
TEXVEC_LINESW, 63, 24, 16, TEXVEC_LINEDW, 63, 21, 4,
TEXVEC_LINEDW, 32, 36, 4, TEXVEC_COLOR, 0,
TEXVEC_FILL, 31, 8, TEXVEC_COLOR, 2,
TEXVEC_FILL, 33, 38, TEXVEC_COLOR, 3,
TEXVEC_FILL, 30, 38, TEXVEC_EXIT },
/* */
(char[]) { TEXVEC_EXIT },
/* */
(char[]) { TEXVEC_EXIT },
/* TEXINDEX_NOR */
(char[]) { TEXVEC_COLOR, 9, TEXVEC_LINESE, 32, 2, 16,
TEXVEC_LINESE, 0, 18, 16, TEXVEC_LINESW, 63, 18, 16,
TEXVEC_LINEDW, 0, 18, 4, TEXVEC_LINEDW, 31, 33, 4,
TEXVEC_LINESW, 31, 2, 16, TEXVEC_LINESE, 0, 21, 16,
TEXVEC_LINESW, 63, 21, 16, TEXVEC_LINEDW, 63, 18, 4,
TEXVEC_LINEDW, 32, 33, 4, TEXVEC_COLOR, 8,
TEXVEC_FILL, 31, 5, TEXVEC_COLOR, 10,
TEXVEC_FILL, 33, 35, TEXVEC_COLOR, 11,
TEXVEC_FILL, 30, 35, TEXVEC_EXIT },
/* TEXINDEX_HOLE */
(char[]) { TEXVEC_COLOR, 13, TEXVEC_LINESE, 32, 9, 12,
TEXVEC_LINESE, 8, 21, 12, TEXVEC_LINESW, 31, 9, 12,
TEXVEC_LINESW, 55, 21, 12, TEXVEC_LINESE, 32, 12, 9,
TEXVEC_LINESE, 14, 21, 9, TEXVEC_LINESW, 31, 12, 9,
TEXVEC_LINESW, 49, 21, 9, TEXVEC_COLOR, 14,
TEXVEC_LINEDW, 31, 13, 4, TEXVEC_LINESW, 31, 16, 7,
TEXVEC_FILL, 30, 14, TEXVEC_COLOR, 12,
TEXVEC_FILL, 32, 11, TEXVEC_COLOR, 15,
TEXVEC_LINEDW, 32, 13, 4, TEXVEC_LINESE, 32, 16, 7,
TEXVEC_FILL, 33, 14, TEXVEC_COLOR, 16,
TEXVEC_FILL, 31, 19, TEXVEC_EXIT }
};
static void _texture_draw(int t, int x, int y);
/*! \brief */
static void _image_create(void) {
display = XOpenDisplay(0);
window = XCreateSimpleWindow(display,
RootWindow(display, DefaultScreen(display)),
0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
image = XCreateImage(display,
DefaultVisual(display, DefaultScreen(display)),
DefaultDepth(display, DefaultScreen(display)),
2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
}
/* \brief , */
static void _image_reset(void) {
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++)
pixdata[y][x] = 0;
}
/*! \brief
* \param[in] elem
* \return */
static int _map2texture(char elem) {
return ((elem >> 4) & 1) << 2 | (elem & 3);
}
/*! \brief */
static void _image_compile(void) {
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
_texture_draw(_map2texture(mapdata[y][x]), x, y);
}
/*! \brief */
static void _image_draw(void) {
XPutImage(display, window,
DefaultGC(display, DefaultScreen(display)),
image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
XMapWindow(display, window);
XFlush(display);
}
/*! \brief */
static void _image_drill(void) {
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if ((x % 14 == 2) && (y % 4 == 3))
_texture_draw(TEXINDEX_HOLE, x, y);
}
/*! \brief LCD-
* \param[in] x X-
* \param[in] y Y- */
static void _shader_lcd(int x, int y) {
pixdata[y][x] &= 0xe0e0e0 | (31 << ((x % 3) << 3));
}
/*! \brief
* \param[in] x X-
* \param[in] y Y- */
static void _shader_noise(int x, int y) {
pixdata[y][x] += 0x0f0f0f & (random *= 16777619);
}
/*! \brief */
static void _image_postprocess(void) {
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++) {
_shader_lcd(x, y);
_shader_noise(x, y);
}
}
/*! \brief
* \param[in] t
* \param[in] x X
* \param[in] y Y */
static void _texture_draw(int t, int x, int y) {
for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
if (textures[t][ty][tx])
pixdata[ty +
y * (TEXTURE_TOP_HEIGHT / 2) +
x * (TEXTURE_TOP_HEIGHT / 2)]
[tx +
IMAGE_SHIFTX +
x * (TEXTURE_TOP_WIDTH / 2) -
y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}
/*! \brief
* \param[in] t
* \param[in] x X-
* \param[in] y Y-
* \param[in] source
* \param[in] target */
static void _texture_fill(int t, int x, int y, int source, int target) {
if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT ||
x < 0 || y < 0) ||
(textures[t][y][x] == target) ||
(textures[t][y][x] != source))
return;
textures[t][y][x] = target;
_texture_fill(t, x - 1, y, source, target);
_texture_fill(t, x + 1, y, source, target);
_texture_fill(t, x, y - 1, source, target);
_texture_fill(t, x, y + 1, source, target);
}
/*! \brief SE
* \param[in] t
* \param[in] x X-
* \param[in] y Y-
* \param[in] c
* \param[in] color */
static void _texture_linese(int t, int x, int y, int c, int color) {
while (c--) {
textures[t][y][x++] = color;
textures[t][y++][x++] = color;
}
}
/*! \brief SW
* \param[in] t
* \param[in] x X-
* \param[in] y Y-
* \param[in] c
* \param[in] color */
static void _texture_linesw(int t, int x, int y, int c, int color) {
while (c--) {
textures[t][y][x--] = color;
textures[t][y++][x--] = color;
}
}
/*! \brief
* \param[in] t
* \param[in] x X-
* \param[in] y Y-
* \param[in] c
* \param[in] color */
static void _texture_linedown(int t, int x, int y, int c, int color) {
while (c--)
textures[t][y++][x] = color;
}
/*! \brief -
* \param[in] filename - */
static void _map_read(const char * filename) {
int f = open(filename, 0);
read(f, mapdata, MAP_FILEDATA);
close(f);
}
/*! \brief -
* */
static void _map_wire_inputs(void) {
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if ((x % 14 == 2) && (y % 4 == 3))
mapdata[y][x] = MAPCHAR_WIRE;
}
/*! \brief
* \param[in] t ,
* \param[in] x X-
* \param[in] y Y-
* \param[in] c
* \param[in] l */
static void _map_fill(int t, int x, int y, int c, int l) {
if ((x >= MAP_WIDTH || y >= MAP_HEIGHT ||
x < 0 || y < 0) || (mapdata[y][x] == l)
|| (mapdata[y][x] != c))
return;
mapdata[y][x] = l;
_map_fill(t, x - 1, y, c, l);
_map_fill(t, x + 1, y, c, l);
_map_fill(t, x, y - 1, c, l);
_map_fill(t, x, y + 1, c, l);
}
/*! \brief
* .
* \param[in] counter */
static void _map_wire_counter(int counter) {
_map_fill(0, 2, 3, mapdata[3][2], counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 7, mapdata[7][2], counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}
/*! \brief () NOR- */
static void _map_process_gates(void) {
for (int i = 0; i < MAP_ITERATIONS; i++)
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if (mapdata[y][x] == MAPCHAR_NOR)
_map_fill(0, x + 1, y, mapdata[y][x + 1],
!(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
|| mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ?
MAPCHAR_PLUS : MAPCHAR_MINUS);
}
/* */
int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
int main(int argc, char * args[]) {
_image_create();
for (int tex = 0; tex < TEXTURE_COUNT; tex++) {
char * ptr = vecdata[tex];
int c = 0;
while (*ptr != TEXVEC_EXIT) {
switch (*ptr) {
case TEXVEC_LINESE:
_texture_linese(tex, ptr[1], ptr[2], ptr[3], c);
ptr += 4;
break;
case TEXVEC_LINESW:
_texture_linesw(tex, ptr[1], ptr[2], ptr[3], c);
ptr += 4;
break;
case TEXVEC_LINEDW:
_texture_linedown(tex, ptr[1], ptr[2], ptr[3], c);
ptr += 4;
break;
case TEXVEC_FILL:
_texture_fill(tex, ptr[1], ptr[2], 0, c);
ptr += 3;
break;
case TEXVEC_REPEAT:
ptr = vecdata[ptr[1]];
break;
case TEXVEC_COLOR:
c = _x[ptr[1] / 4] - 1643277 * (ptr[1] % 4);
ptr += 2;
break;
}
}
}
unsigned int counter = 1;
while (counter++) {
_map_read(args[ARG_BLUEPRINT]);
_map_wire_inputs();
_map_wire_counter(counter);
_map_process_gates();
_image_reset();
_image_compile();
_image_drill();
_image_postprocess();
_image_draw();
sleep(1);
}
return 0;
}
命令「TEXVEC_COLOR」の後に続く最大数は16です。テーブル全体を取得するための最も簡単なコードを書いてみましょう。
これで、復号化されたパレットが手元にあるので、その使用機能を置き換えて、定数テーブルの色の復号化を書き込むことができます。テクスチャを作成する機能を強調します。
リファクタリング後の完全なコード:
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/* */
/*! \brief */
#define IMAGE_WIDTH (1220)
/*! \brief */
#define IMAGE_HEIGHT (616)
/*! \brief */
#define IMAGE_SHIFTX (580)
/*! \brief */
#define TEXTURE_COUNT (8)
/*! \brief */
#define TEXTURE_WIDTH (64)
/*! \brief */
#define TEXTURE_HEIGHT (40)
/*! \brief */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief */
#define TEXTURE_TOP_HEIGHT (32)
/*! \brief */
#define MAP_WIDTH (19)
/*! \brief */
#define MAP_HEIGHT (19)
/*! \brief -. '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief NOR- */
#define MAP_ITERATIONS (20)
/*! \brief - */
enum map_characters {
MAPCHAR_WIRE = '.', /**< (ASCII = 46) */
MAPCHAR_PLUS = '+', /**< ( ) (ASCII = 43) */
MAPCHAR_MINUS = '-', /**< ( ) (ASCII = 45) */
MAPCHAR_NOR = '>', /**< NOR- (ASCII = 62) */
MAPCHAR_EMPTY = ' ', /**< (ASCII = 32) */
};
/*! \brief */
enum textures_indexes {
TEXINDEX_EMPTY = (0), /**< */
TEXINDEX_MINUS = (1), /**< " " */
TEXINDEX_WIRE = (2), /**< */
TEXINDEX_PLUS = (3), /**< "" */
/**/
TEXINDEX_NOR = (6), /**< NOR- */
TEXINDEX_HOLE = (7) /**< */
};
/*! \brief */
enum textures_instructions {
TEXVEC_LINESE = (0), /**< SE */
TEXVEC_LINESW = (1), /**< SW */
TEXVEC_LINEDW = (2), /**< */
TEXVEC_FILL = (3), /**< */
TEXVEC_EXIT = (4), /**< */
TEXVEC_REPEAT = (5), /**< */
TEXVEC_COLOR = (6) /**< */
};
/*! \brief */
enum program_arguments {
ARG_PROGRAM, /**< */
ARG_BLUEPRINT /**< - */
};
/*! \brief .
* int */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief , */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief .
* '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];
/*! \brief */
int random = 2166136261;
/*! \brief Xlib */
Display * display;
/*! \brief Xlib */
Window window;
/*! \brief */
XImage * image;
/*! \brief
* \note {001} "" {000} */
static const int texturepalette[] = {
/* ▁▁▂▂▃▃▄▄▅▅▆▆▇▇██ */
/* - */ 0xe6ac73, 0xcd9966, 0xb48659, 0x9b734c,
/* - */ 0x806040, 0x674d33, 0x4e3a26, 0x352719,
/* */ 0x59b368, 0x40a05b, 0x278d4e, 0x0e7a41,
/* */ 0xc6c6c6, 0xadb3b9, 0x94a0ac, 0x7b8d9f,
/* */ 0x000001
};
/*! \brief */
static const char * vecdata[TEXTURE_COUNT] = {
/* TEXINDEX_EMPTY */
(char[]) { TEXVEC_EXIT },
/* TEXINDEX_MINUS */
(char[]) { TEXVEC_COLOR, 5, TEXVEC_LINESE, 32, 5, 16,
TEXVEC_LINESE, 0, 21, 16, TEXVEC_LINESW, 63, 21, 16,
TEXVEC_LINEDW, 0, 21, 4, TEXVEC_LINEDW, 31, 36, 4,
TEXVEC_LINESW, 31, 5, 16, TEXVEC_LINESE, 0, 24, 16,
TEXVEC_LINESW, 63, 24, 16, TEXVEC_LINEDW, 63, 21, 4,
TEXVEC_LINEDW, 32, 36, 4, TEXVEC_COLOR, 4,
TEXVEC_FILL, 31, 8, TEXVEC_COLOR, 6,
TEXVEC_FILL, 33, 38, TEXVEC_COLOR, 7,
TEXVEC_FILL, 30, 38, TEXVEC_EXIT },
/* TEXINDEX_WIRE */
(char[]) { TEXVEC_REPEAT, 1 },
/* TEXINDEX_PLUS */
(char[]) { TEXVEC_COLOR, 1, TEXVEC_LINESE, 32, 5, 16,
TEXVEC_LINESE, 0, 21, 16, TEXVEC_LINESW, 63, 21, 16,
TEXVEC_LINEDW, 63, 21, 4, TEXVEC_LINEDW, 31, 36, 4,
TEXVEC_LINESW, 31, 5, 16, TEXVEC_LINESE, 0, 24, 16,
TEXVEC_LINESW, 63, 24, 16, TEXVEC_LINEDW, 63, 21, 4,
TEXVEC_LINEDW, 32, 36, 4, TEXVEC_COLOR, 0,
TEXVEC_FILL, 31, 8, TEXVEC_COLOR, 2,
TEXVEC_FILL, 33, 38, TEXVEC_COLOR, 3,
TEXVEC_FILL, 30, 38, TEXVEC_EXIT },
/* */
(char[]) { TEXVEC_EXIT },
/* */
(char[]) { TEXVEC_EXIT },
/* TEXINDEX_NOR */
(char[]) { TEXVEC_COLOR, 9, TEXVEC_LINESE, 32, 2, 16,
TEXVEC_LINESE, 0, 18, 16, TEXVEC_LINESW, 63, 18, 16,
TEXVEC_LINEDW, 0, 18, 4, TEXVEC_LINEDW, 31, 33, 4,
TEXVEC_LINESW, 31, 2, 16, TEXVEC_LINESE, 0, 21, 16,
TEXVEC_LINESW, 63, 21, 16, TEXVEC_LINEDW, 63, 18, 4,
TEXVEC_LINEDW, 32, 33, 4, TEXVEC_COLOR, 8,
TEXVEC_FILL, 31, 5, TEXVEC_COLOR, 10,
TEXVEC_FILL, 33, 35, TEXVEC_COLOR, 11,
TEXVEC_FILL, 30, 35, TEXVEC_EXIT },
/* TEXINDEX_HOLE */
(char[]) { TEXVEC_COLOR, 13, TEXVEC_LINESE, 32, 9, 12,
TEXVEC_LINESE, 8, 21, 12, TEXVEC_LINESW, 31, 9, 12,
TEXVEC_LINESW, 55, 21, 12, TEXVEC_LINESE, 32, 12, 9,
TEXVEC_LINESE, 14, 21, 9, TEXVEC_LINESW, 31, 12, 9,
TEXVEC_LINESW, 49, 21, 9, TEXVEC_COLOR, 14,
TEXVEC_LINEDW, 31, 13, 4, TEXVEC_LINESW, 31, 16, 7,
TEXVEC_FILL, 30, 14, TEXVEC_COLOR, 12,
TEXVEC_FILL, 32, 11, TEXVEC_COLOR, 15,
TEXVEC_LINEDW, 32, 13, 4, TEXVEC_LINESE, 32, 16, 7,
TEXVEC_FILL, 33, 14, TEXVEC_COLOR, 16,
TEXVEC_FILL, 31, 19, TEXVEC_EXIT }
};
static void _texture_draw(int t, int x, int y);
/*! \brief */
static void _image_create(void) {
display = XOpenDisplay(0);
window = XCreateSimpleWindow(display,
RootWindow(display, DefaultScreen(display)),
0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
image = XCreateImage(display,
DefaultVisual(display, DefaultScreen(display)),
DefaultDepth(display, DefaultScreen(display)),
2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
}
/* \brief , */
static void _image_reset(void) {
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++)
pixdata[y][x] = 0;
}
/*! \brief
* \param[in] elem
* \return */
static int _map2texture(char elem) {
return ((elem >> 4) & 1) << 2 | (elem & 3);
}
/*! \brief */
static void _image_compile(void) {
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
_texture_draw(_map2texture(mapdata[y][x]), x, y);
}
/*! \brief */
static void _image_draw(void) {
XPutImage(display, window,
DefaultGC(display, DefaultScreen(display)),
image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
XMapWindow(display, window);
XFlush(display);
}
/*! \brief */
static void _image_drill(void) {
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if ((x % 14 == 2) && (y % 4 == 3))
_texture_draw(TEXINDEX_HOLE, x, y);
}
/*! \brief LCD-
* \param[in] x X-
* \param[in] y Y- */
static void _shader_lcd(int x, int y) {
pixdata[y][x] &= 0xe0e0e0 | (31 << ((x % 3) << 3));
}
/*! \brief
* \param[in] x X-
* \param[in] y Y- */
static void _shader_noise(int x, int y) {
pixdata[y][x] += 0x0f0f0f & (random *= 16777619);
}
/*! \brief */
static void _image_postprocess(void) {
for (int y = 0; y < IMAGE_HEIGHT; y++)
for (int x = 0; x < IMAGE_WIDTH; x++) {
_shader_lcd(x, y);
_shader_noise(x, y);
}
}
/*! \brief
* \param[in] t
* \param[in] x X
* \param[in] y Y */
static void _texture_draw(int t, int x, int y) {
for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
if (textures[t][ty][tx])
pixdata[ty +
y * (TEXTURE_TOP_HEIGHT / 2) +
x * (TEXTURE_TOP_HEIGHT / 2)]
[tx +
IMAGE_SHIFTX +
x * (TEXTURE_TOP_WIDTH / 2) -
y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}
/*! \brief
* \param[in] t
* \param[in] x X-
* \param[in] y Y-
* \param[in] source
* \param[in] target */
static void _texture_fill(int t, int x, int y, int source, int target) {
if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT ||
x < 0 || y < 0) ||
(textures[t][y][x] == target) ||
(textures[t][y][x] != source))
return;
textures[t][y][x] = target;
_texture_fill(t, x - 1, y, source, target);
_texture_fill(t, x + 1, y, source, target);
_texture_fill(t, x, y - 1, source, target);
_texture_fill(t, x, y + 1, source, target);
}
/*! \brief SE
* \param[in] t
* \param[in] x X-
* \param[in] y Y-
* \param[in] c
* \param[in] color */
static void _texture_linese(int t, int x, int y, int c, int color) {
while (c--) {
textures[t][y][x++] = color;
textures[t][y++][x++] = color;
}
}
/*! \brief SW
* \param[in] t
* \param[in] x X-
* \param[in] y Y-
* \param[in] c
* \param[in] color */
static void _texture_linesw(int t, int x, int y, int c, int color) {
while (c--) {
textures[t][y][x--] = color;
textures[t][y++][x--] = color;
}
}
/*! \brief
* \param[in] t
* \param[in] x X-
* \param[in] y Y-
* \param[in] c
* \param[in] color */
static void _texture_linedown(int t, int x, int y, int c, int color) {
while (c--)
textures[t][y++][x] = color;
}
/*! \brief , */
static void _textures_create(void) {
for (int tex = 0; tex < TEXTURE_COUNT; tex++) {
const char * ptr = vecdata[tex];
int c = 0;
while (*ptr != TEXVEC_EXIT) {
switch (*ptr) {
case TEXVEC_LINESE:
_texture_linese(tex, ptr[1], ptr[2], ptr[3], c);
ptr += 4;
break;
case TEXVEC_LINESW:
_texture_linesw(tex, ptr[1], ptr[2], ptr[3], c);
ptr += 4;
break;
case TEXVEC_LINEDW:
_texture_linedown(tex, ptr[1], ptr[2], ptr[3], c);
ptr += 4;
break;
case TEXVEC_FILL:
_texture_fill(tex, ptr[1], ptr[2], 0, c);
ptr += 3;
break;
case TEXVEC_REPEAT:
ptr = vecdata[ptr[1]];
break;
case TEXVEC_COLOR:
c = texturepalette[ptr[1]];
ptr += 2;
break;
}
}
}
}
/*! \brief -
* \param[in] filename - */
static void _map_read(const char * filename) {
int f = open(filename, 0);
read(f, mapdata, MAP_FILEDATA);
close(f);
}
/*! \brief -
* */
static void _map_wire_inputs(void) {
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if ((x % 14 == 2) && (y % 4 == 3))
mapdata[y][x] = MAPCHAR_WIRE;
}
/*! \brief
* \param[in] t ,
* \param[in] x X-
* \param[in] y Y-
* \param[in] c
* \param[in] l */
static void _map_fill(int t, int x, int y, int c, int l) {
if ((x >= MAP_WIDTH || y >= MAP_HEIGHT ||
x < 0 || y < 0) || (mapdata[y][x] == l)
|| (mapdata[y][x] != c))
return;
mapdata[y][x] = l;
_map_fill(t, x - 1, y, c, l);
_map_fill(t, x + 1, y, c, l);
_map_fill(t, x, y - 1, c, l);
_map_fill(t, x, y + 1, c, l);
}
/*! \brief
* .
* \param[in] counter */
static void _map_wire_counter(int counter) {
_map_fill(0, 2, 3, mapdata[3][2], counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 7, mapdata[7][2], counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
_map_fill(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}
/*! \brief () NOR- */
static void _map_process_gates(void) {
for (int i = 0; i < MAP_ITERATIONS; i++)
for (int y = 0; y < MAP_HEIGHT; y++)
for (int x = 0; x < MAP_WIDTH; x++)
if (mapdata[y][x] == MAPCHAR_NOR)
_map_fill(0, x + 1, y, mapdata[y][x + 1],
!(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
|| mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ?
MAPCHAR_PLUS : MAPCHAR_MINUS);
}
int main(int argc, char * args[]) {
_image_create();
_textures_create();
unsigned int counter = 1;
while (counter++) {
_map_read(args[ARG_BLUEPRINT]);
_map_wire_inputs();
_map_wire_counter(counter);
_map_process_gates();
_image_reset();
_image_compile();
_image_drill();
_image_postprocess();
_image_draw();
sleep(1);
}
return 0;
}
エピローグ
それで全部です。入賞しなかったにも関わらず、かなり不思議な体験でした(作品の受付開始の2日前に亡くなったHDDが貢献しました)。可能な限り読みにくく、同時に言語の観点から絶対的に有効なコードの記述に問題がありました。しかし、面白くなかったとは言えません。トークンをカウントするユーティリティが、コードが制限を2000以上のトークンで超えてルールに違反していると言い、それを短縮する方法がわからない場合、それは課題です。ファイルサイズが制限を超えており、何らかのグラフィック効果を追加したい場合、これは課題です。非常に多くの機能に対応することは困難であり、ユーティリティの出力を読み取ることはより甘く、数百の修正の後、最終的にコードをアンロードできると述べました。読者にコンテストに参加することをお勧めします。参加してあなたの強さをテストします。
はい、それは賞や賞を与えませんが、あなたはあなたがIOCCCウェブサイトでニックネームzhestokyshvellerの下に隠れていることを知っているでしょう。