// File: /workspace/github_cpp_makefile_star2_O2/kipa00[P]AplusB-mc/compiler/main.cpp
// Function: main
int main(int argc, char *argv[]) {
	if (argc <= 1) {
		fprintf(stderr, "Usage: %s <region file name> [input list]\n", argv[0]);
		return -1;
	} else if (argc == 2) {
		fprintf(stderr, "Warning: no input specified\n");
	}
	vector<int> input_order;
	for (int i=2; i<argc; ++i) {
		int v = color_to_int(argv[i]);
		if (v < 0) {
			fprintf(stderr, "Error: unknown color '%s'\n", argv[i]);
			return -1;
		}
		input_order.push_back(v);
	}
	FILE *fp = fopen(argv[1], "rb");
	world w;
	try {
		w.init(fp);
	} catch (int err) {
		fprintf(stderr, "Compilation aborted.\n");
		return -1;
	}
	fclose(fp);

	int **u = new int *[16384], cnt = 0;
	memset(u, 0, sizeof(int *) * 16384);
	traverse_world(w, [&] (int x, int y, int z) {
		if (is_redstone_component(w, x, y, z)) {
			int **ptr = u + (((z >> 4) << 9) | ((x >> 4) << 4) | (y >> 4));
			if (!*ptr) {
				*ptr = new int[4096];
				memset(*ptr, 0, sizeof(int) * 4096);
			}
			(*ptr)[((z & 15) << 8) | ((x & 15) << 4) | (y & 15)] = ++cnt;
		}
	});

	fp = fopen("a.out", "wb");
	traverse_world(w, [&] (int x, int y, int z) {
		vector<int> info;
		const int type = analyze(w, x, y, z, info);
		if (type) {
			int byte_type = 0;
			if (type == 1) {
				byte_type = 16 | (w.getXYZ(x, y, z) & 15);
			} else {
				byte_type = (type << 4) | (w.getXYZ(x, y, z) & POWERED ? 15 : 0);
			}
			write_byte(fp, byte_type);
			for (const int &x : info) {
				write_int(fp, x >= 0 ? u[x >> 12][x & 4095] : -1);
			}
			write_int(fp, -1);
			if (type == 1 || type == 2) {
				for (int i=0; i<wide_len; ++i) {
					const int nx = x + wide_dx[i], ny = y + wide_dy[i], nz = z + wide_dz[i];
					if (is_redstone_component(w, nx, ny, nz)) {
						vector<int> temp;
						analyze(w, nx, ny, nz, temp);
						const int target = pack(x, y, z);
						const int idx = pack(nx, ny, nz);
						for (const int &v : temp) {
							if (v == target) {
								write_int(fp, u[idx >> 12][idx & 4095]);
								break;
							}
						}
					}
				}
			} else {
				for (int i=0; i<narrow_len; ++i) {
					int nx = x + narrow_dx[i], ny = y + narrow_dy[i], nz = z + narrow_dz[i];
					if (is_redstone_component(w, nx, ny, nz)) {
						const int idx = pack(nx, ny, nz);
						write_int(fp, u[idx >> 12][idx & 4095]);
					}
					if (type != 10) {
						switch (w.getXYZ(x, y, z) & 3) {
							case EAST: --nx; break;
							case WEST: ++nx; break;
							case SOUTH: --nz; break;
							case NORTH: ++nz; break;
						}
						if (is_redstone_component(w, nx, ny, nz) && !(nx == x && nz == z)) {
							int idx = pack(nx, ny, nz);
							write_int(fp, u[idx >> 12][idx & 4095]);
						}
					}
				}
			}
			write_int(fp, -1);
		}
	});
	write_byte(fp, -1);

	vector<std::pair<int, int> > inputs[16], output;
	traverse_world(w, [&] (int x, int y, int z) {
		byte fetched = w.getXYZ(x, y, z);
		if ((fetched & BLOCK_ONLY) == LEVER) {
			int nx = x, ny = y, nz = z;
			switch (fetched & 3) {
				case EAST: --nx; break;
				case WEST: ++nx; break;
				case SOUTH: --nz; break;
				case NORTH: ++nz; break;
			}
			byte facing = w.getXYZ(nx, ny, nz);
			if ((facing & BLOCK_ONLY) == CONCRETE) {
				inputs[facing & 15].emplace_back((z << 17) | (x << 8) | y, pack(x, y, z));
			}
		} else if ((fetched & BLOCK_ONLY) == REDSTONE_LAMP) {
			output.emplace_back((z << 17) | (x << 8) | y, pack(x, y, z));
		}
	});
	for (int i=0; i<16; ++i) {
		sort(inputs[i].begin(), inputs[i].end());
	}
	sort(output.begin(), output.end());

	for (const int &i : input_order) {
		for (const auto &[_, idx] : inputs[i]) {
			write_int(fp, u[idx >> 12][idx & 4095]);
		}
		write_int(fp, -1);
	}
	write_int(fp, -1);
	for (const auto &[_, idx] : output) {
		write_int(fp, u[idx >> 12][idx & 4095]);
	}
	write_int(fp, -1);
	fclose(fp);
	return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x268, %rsp            # imm = 0x268
movq %rsi, %r14
cmpl $0x1, %edi
jle 0x2845
movl %edi, %ebx
cmpl $0x2, %edi
je 0x2865
xorps %xmm0, %xmm0
leaq 0x40(%rsp), %rax
movaps %xmm0, (%rax)
andq $0x0, 0x10(%rax)
movl %ebx, %r15d
pushq $0x2
popq %rbx
leaq 0xc0(%rsp), %r12
leaq 0xe0(%rsp), %r13
cmpq %r15, %rbx
jae 0x2539
movq (%r14,%rbx,8), %rsi
movq %r12, %rdi
leaq 0x20(%rsp), %rdx
callq 0x2fce
movq %r12, %rdi
callq 0x70a8
movl %eax, %ebp
movq %r12, %rdi
callq 0x20a0
movl %ebp, 0xe0(%rsp)
testl %ebp, %ebp
js 0x2886
leaq 0x40(%rsp), %rdi
movq %r13, %rsi
callq 0x300a
incq %rbx
jmp 0x24f0
movq 0x8(%r14), %rdi
leaq 0x5d2f(%rip), %rsi      # 0x8273
callq 0x21a0
movq %rax, (%rsp)
leaq 0x10(%rsp), %rdi
callq 0x4acc
movq (%rsp), %rsi
leaq 0x10(%rsp), %r14
movq %r14, %rdi
callq 0x4ad2
movq (%rsp), %rdi
callq 0x2140
movl $0x20000, %edi          # imm = 0x20000
callq 0x2030
movq %rax, 0x8(%rsp)
andl $0x0, 0x1c(%rsp)
movl $0x20000, %edx          # imm = 0x20000
movq %rax, %rdi
xorl %esi, %esi
callq 0x20d0
xorps %xmm0, %xmm0
movaps %xmm0, 0xa0(%rsp)
movaps %xmm0, 0xb0(%rsp)
pushq $0x18
popq %rdi
callq 0x2150
movq %r14, (%rax)
leaq 0x8(%rsp), %rbx
movq %rbx, 0x8(%rax)
leaq 0x1c(%rsp), %rcx
movq %rcx, 0x10(%rax)
leaq 0xa0(%rsp), %rsi
movq %rax, (%rsi)
leaq 0x3aa(%rip), %rax       # 0x2980
movq %rax, 0x18(%rsi)
leaq 0x44f(%rip), %rax       # 0x2a30
movq %rax, 0x10(%rsi)
movq %r14, %rdi
callq 0x236c
leaq 0xa0(%rsp), %rdi
callq 0x3028
leaq 0x5c8b(%rip), %rdi      # 0x828c
leaq 0x5c8a(%rip), %rsi      # 0x8292
callq 0x21a0
movq %rax, (%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0x80(%rsp)
movaps %xmm0, 0x90(%rsp)
pushq $0x18
popq %rdi
callq 0x2150
movq %r14, (%rax)
movq %rsp, %rcx
movq %rcx, 0x8(%rax)
movq %rbx, 0x10(%rax)
leaq 0x80(%rsp), %rsi
movq %rax, (%rsi)
leaq 0x444(%rip), %rax       # 0x2a90
movq %rax, 0x18(%rsi)
leaq 0x7a5(%rip), %rax       # 0x2dfc
movq %rax, 0x10(%rsi)
movq %r14, %rdi
callq 0x236c
leaq 0x80(%rsp), %rdi
callq 0x3028
movq (%rsp), %rsi
pushq $-0x1
popq %rdi
callq 0x21c0
leaq 0xe0(%rsp), %r15
movl $0x180, %edx            # imm = 0x180
movq %r15, %rdi
xorl %esi, %esi
callq 0x20d0
andq $0x0, 0x30(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0x20(%rsp)
movaps %xmm0, 0x60(%rsp)
movaps %xmm0, 0x70(%rsp)
pushq $0x18
popq %rdi
callq 0x2150
movq %r14, (%rax)
movq %r15, 0x8(%rax)
leaq 0x20(%rsp), %rcx
movq %rcx, 0x10(%rax)
leaq 0x60(%rsp), %rsi
movq %rax, (%rsi)
leaq 0x78a(%rip), %rax       # 0x2e5c
movq %rax, 0x18(%rsi)
leaq 0x85d(%rip), %rax       # 0x2f3a
movq %rax, 0x10(%rsi)
movq %r14, %rdi
callq 0x236c
leaq 0x60(%rsp), %rdi
callq 0x3028
pushq $0x8
popq %rbx
cmpq $0x188, %rbx            # imm = 0x188
je 0x271a
movq 0xd8(%rsp,%rbx), %rdi
movq 0xe0(%rsp,%rbx), %rsi
callq 0x341f
addq $0x18, %rbx
jmp 0x26f6
movq 0x20(%rsp), %rdi
movq 0x28(%rsp), %rsi
callq 0x341f
movq 0x40(%rsp), %r14
movq 0x48(%rsp), %r15
pushq $-0x1
popq %rbx
cmpq %r15, %r14
je 0x2796
movslq (%r14), %rax
imulq $0x18, %rax, %rax
movq 0xe0(%rsp,%rax), %r12
movq 0xe8(%rsp,%rax), %r13
cmpq %r13, %r12
je 0x2785
movq (%rsp), %rdi
movq 0x8(%rsp), %rax
movl 0x4(%r12), %ecx
movl %ecx, %edx
sarl $0xc, %edx
movslq %edx, %rdx
movq (%rax,%rdx,8), %rax
andl $0xfff, %ecx            # imm = 0xFFF
movl (%rax,%rcx,4), %esi
callq 0x245e
addq $0x8, %r12
jmp 0x2752
movq (%rsp), %rdi
movl %ebx, %esi
callq 0x245e
addq $0x4, %r14
jmp 0x2736
movq (%rsp), %rdi
pushq $-0x1
popq %rsi
callq 0x245e
movq 0x20(%rsp), %rbx
movq 0x28(%rsp), %r14
cmpq %r14, %rbx
je 0x27dd
movq (%rsp), %rdi
movq 0x8(%rsp), %rax
movl 0x4(%rbx), %ecx
movl %ecx, %edx
sarl $0xc, %edx
movslq %edx, %rdx
movq (%rax,%rdx,8), %rax
andl $0xfff, %ecx            # imm = 0xFFF
movl (%rax,%rcx,4), %esi
callq 0x245e
addq $0x8, %rbx
jmp 0x27ac
movq (%rsp), %rdi
pushq $-0x1
popq %rsi
callq 0x245e
movq (%rsp), %rdi
callq 0x2140
leaq 0x20(%rsp), %rdi
callq 0x325c
movl $0x168, %ebx            # imm = 0x168
leaq (%rsp,%rbx), %rdi
addq $0xe0, %rdi
callq 0x325c
addq $-0x18, %rbx
cmpq $-0x18, %rbx
jne 0x2801
xorl %ebx, %ebx
leaq 0x10(%rsp), %rdi
callq 0x4e1c
leaq 0x40(%rsp), %rdi
callq 0x3050
movl %ebx, %eax
addq $0x268, %rsp            # imm = 0x268
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x9794(%rip), %rax      # 0xbfe0
movq (%rax), %rdi
movq (%r14), %rdx
leaq 0x59b7(%rip), %rsi      # 0x8210
xorl %eax, %eax
callq 0x21f0
pushq $-0x1
popq %rbx
jmp 0x2831
movq 0x9774(%rip), %rax      # 0xbfe0
movq (%rax), %rcx
leaq 0x59c5(%rip), %rdi      # 0x823b
pushq $0x1c
popq %rsi
pushq $0x1
popq %rdx
callq 0x2260
jmp 0x24ca
movq 0x9753(%rip), %rax      # 0xbfe0
movq (%rax), %rdi
movq (%r14,%rbx,8), %rdx
leaq 0x59bd(%rip), %rsi      # 0x8258
xorl %eax, %eax
callq 0x21f0
pushq $-0x1
popq %rbx
jmp 0x2827
jmp 0x291f
jmp 0x28ab
movq %rax, %rbx
leaq 0x60(%rsp), %rdi
callq 0x3028
jmp 0x2922
jmp 0x28bc
movq %rax, %rbx
leaq 0x80(%rsp), %rdi
jmp 0x28d6
jmp 0x28cb
movq %rax, %rbx
leaq 0xa0(%rsp), %rdi
callq 0x3028
jmp 0x294c
movq %rax, %rbx
jmp 0x294c
movq %rax, %rbx
cmpl $0x1, %edx
jne 0x294c
movq %rbx, %rdi
callq 0x2080
movq 0x96e7(%rip), %rax      # 0xbfe0
movq (%rax), %rcx
leaq 0x5973(%rip), %rdi      # 0x8276
pushq $0x15
popq %rsi
pushq $0x1
popq %rdx
callq 0x2260
callq 0x2220
pushq $-0x1
popq %rbx
jmp 0x281d
jmp 0x296a
jmp 0x296a
movq %rax, %rbx
leaq 0x20(%rsp), %rdi
callq 0x325c
movl $0x168, %r14d           # imm = 0x168
leaq (%rsp,%r14), %rdi
addq $0xe0, %rdi
callq 0x325c
addq $-0x18, %r14
cmpq $-0x18, %r14
jne 0x2932
leaq 0x10(%rsp), %rdi
callq 0x4e1c
jmp 0x296d
movq %rax, %rbx
leaq 0xc0(%rsp), %rdi
callq 0x20a0
jmp 0x296d
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
callq 0x3050
movq %rbx, %rdi
callq 0x2240
nop