// File: /workspace/github_cpp_makefile_star2_O3/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, %rbx
cmpl $0x1, %edi
jle 0x2b42
cmpl $0x2, %edi
je 0x2b51
xorps %xmm0, %xmm0
leaq 0x30(%rsp), %rax
movaps %xmm0, (%rax)
movq $0x0, 0x10(%rax)
movl %edi, %r13d
movl $0x2, %r14d
leaq 0xc0(%rsp), %r15
leaq 0x10(%rsp), %r12
movq (%rbx,%r14,8), %rsi
movq %r15, %rdi
movq %r12, %rdx
callq 0x3392
movq %r15, %rdi
callq 0x7c78
movl %eax, %ebp
movq 0xc0(%rsp), %rdi
leaq 0xd0(%rsp), %rax
cmpq %rax, %rdi
je 0x2725
movq 0xd0(%rsp), %rsi
incq %rsi
callq 0x2150
movl %ebp, 0xe0(%rsp)
testl %ebp, %ebp
js 0x2b60
movq 0x38(%rsp), %rsi
cmpq 0x40(%rsp), %rsi
je 0x274d
movl %ebp, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x38(%rsp)
jmp 0x275f
leaq 0x30(%rsp), %rdi
leaq 0xe0(%rsp), %rdx
callq 0x3470
incq %r14
cmpq %r14, %r13
jne 0x26e7
movq 0x8(%rbx), %rdi
leaq 0x5b01(%rip), %rsi      # 0x8273
callq 0x2190
movq %rax, 0x8(%rsp)
leaq 0x50(%rsp), %rdi
callq 0x4ed8
movq 0x8(%rsp), %rsi
leaq 0x50(%rsp), %rbx
movq %rbx, %rdi
callq 0x4ee0
movq 0x8(%rsp), %rdi
callq 0x2130
movl $0x20000, %edi          # imm = 0x20000
callq 0x2030
movq %rax, 0x48(%rsp)
movl $0x0, 0x5c(%rsp)
movl $0x20000, %edx          # imm = 0x20000
movq %rax, %rdi
xorl %esi, %esi
callq 0x20c0
xorps %xmm0, %xmm0
movaps %xmm0, 0xa0(%rsp)
movaps %xmm0, 0xb0(%rsp)
movl $0x18, %edi
callq 0x2140
movq %rbx, (%rax)
leaq 0x48(%rsp), %r14
movq %r14, 0x8(%rax)
leaq 0x5c(%rsp), %rcx
movq %rcx, 0x10(%rax)
leaq 0xa0(%rsp), %rsi
movq %rax, (%rsi)
leaq 0x4e2(%rip), %rax       # 0x2cee
movq %rax, 0x18(%rsi)
leaq 0x587(%rip), %rax       # 0x2d9e
movq %rax, 0x10(%rsi)
movq %rbx, %rdi
callq 0x256c
movq 0xb0(%rsp), %rax
testq %rax, %rax
je 0x2842
leaq 0xa0(%rsp), %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
leaq 0x5a43(%rip), %rdi      # 0x828c
leaq 0x5a42(%rip), %rsi      # 0x8292
callq 0x2190
movq %rax, 0x8(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0x80(%rsp)
movaps %xmm0, 0x90(%rsp)
movl $0x18, %edi
callq 0x2140
movq %rbx, (%rax)
leaq 0x8(%rsp), %rcx
movq %rcx, 0x8(%rax)
movq %r14, 0x10(%rax)
leaq 0x80(%rsp), %rsi
movq %rax, (%rsi)
leaq 0x569(%rip), %rax       # 0x2e02
movq %rax, 0x18(%rsi)
leaq 0x910(%rip), %rax       # 0x31b4
movq %rax, 0x10(%rsi)
movq %rbx, %rdi
callq 0x256c
movq 0x90(%rsp), %rax
testq %rax, %rax
je 0x28cf
leaq 0x80(%rsp), %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
movq 0x8(%rsp), %rsi
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x21b0
leaq 0xe0(%rsp), %r14
movl $0x180, %edx            # imm = 0x180
movq %r14, %rdi
xorl %esi, %esi
callq 0x20c0
xorps %xmm0, %xmm0
movaps %xmm0, 0x10(%rsp)
movq $0x0, 0x20(%rsp)
movaps %xmm0, 0x60(%rsp)
movaps %xmm0, 0x70(%rsp)
movl $0x18, %edi
callq 0x2140
movq %rbx, (%rax)
movq %r14, 0x8(%rax)
leaq 0x10(%rsp), %rcx
movq %rcx, 0x10(%rax)
leaq 0x60(%rsp), %rsi
movq %rax, (%rsi)
leaq 0x8df(%rip), %rax       # 0x3218
movq %rax, 0x18(%rsi)
leaq 0x9b6(%rip), %rax       # 0x32fa
movq %rax, 0x10(%rsi)
movq %rbx, %rdi
callq 0x256c
movq 0x70(%rsp), %rax
testq %rax, %rax
je 0x2969
leaq 0x60(%rsp), %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
movl $0x8, %r15d
movq 0xd8(%rsp,%r15), %rbx
movq 0xe0(%rsp,%r15), %r14
cmpq %r14, %rbx
je 0x29b1
movq %r14, %rax
subq %rbx, %rax
sarq $0x3, %rax
bsrq %rax, %rdx
xorl $0x3f, %edx
addl %edx, %edx
xorq $0x7e, %rdx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x3739
movq %rbx, %rdi
movq %r14, %rsi
callq 0x37ec
addq $0x18, %r15
cmpq $0x188, %r15            # imm = 0x188
jne 0x296f
movq 0x10(%rsp), %rbx
movq 0x18(%rsp), %r14
cmpq %r14, %rbx
je 0x29fa
movq %r14, %rax
subq %rbx, %rax
sarq $0x3, %rax
bsrq %rax, %rdx
xorl $0x3f, %edx
addl %edx, %edx
xorq $0x7e, %rdx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x3739
movq %rbx, %rdi
movq %r14, %rsi
callq 0x37ec
movq 0x30(%rsp), %rbx
movq 0x38(%rsp), %r14
cmpq %r14, %rbx
je 0x2a68
movslq (%rbx), %rax
leaq (%rax,%rax,2), %rax
movq 0xe0(%rsp,%rax,8), %r15
movq 0xe8(%rsp,%rax,8), %r12
cmpq %r12, %r15
je 0x2a53
movq 0x8(%rsp), %rdi
movq 0x48(%rsp), %rax
movl 0x4(%r15), %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 0x2650
addq $0x8, %r15
jmp 0x2a20
movq 0x8(%rsp), %rdi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x2650
addq $0x4, %rbx
jmp 0x2a04
movq 0x8(%rsp), %rdi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x2650
movq 0x10(%rsp), %rbx
movq 0x18(%rsp), %r14
cmpq %r14, %rbx
je 0x2ab3
movq 0x8(%rsp), %rdi
movq 0x48(%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 0x2650
addq $0x8, %rbx
jmp 0x2a81
movq 0x8(%rsp), %rdi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x2650
movq 0x8(%rsp), %rdi
callq 0x2130
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0x2ae3
movq 0x20(%rsp), %rsi
subq %rdi, %rsi
callq 0x2150
movl $0x180, %ebx            # imm = 0x180
movq 0xc8(%rsp,%rbx), %rdi
testq %rdi, %rdi
je 0x2b05
movq 0xd8(%rsp,%rbx), %rsi
subq %rdi, %rsi
callq 0x2150
addq $-0x18, %rbx
jne 0x2ae8
xorl %ebx, %ebx
leaq 0x50(%rsp), %rdi
callq 0x5236
movq 0x30(%rsp), %rdi
testq %rdi, %rdi
je 0x2b2e
movq 0x40(%rsp), %rsi
subq %rdi, %rsi
callq 0x2150
movl %ebx, %eax
addq $0x268, %rsp            # imm = 0x268
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rbx, %rdi
callq 0x22b9
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
jmp 0x2b2e
leaq 0x30(%rsp), %rdi
callq 0x2260
jmp 0x2767
movq 0x9479(%rip), %rax      # 0xbfe0
movq (%rax), %rdi
movq (%rbx,%r14,8), %rdx
leaq 0x56e3(%rip), %rsi      # 0x8258
xorl %eax, %eax
callq 0x21d0
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
jmp 0x2b17
jmp 0x2c1d
jmp 0x2c1d
jmp 0x2c1d
movq %rax, %rbx
movq 0x70(%rsp), %rax
testq %rax, %rax
je 0x2c85
leaq 0x60(%rsp), %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
jmp 0x2c85
jmp 0x2c1d
movq %rax, %rbx
xorl %edi, %edi
jmp 0x2c8a
movq %rax, %rbx
movq 0x90(%rsp), %rax
testq %rax, %rax
je 0x2cc5
leaq 0x80(%rsp), %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
jmp 0x2cc5
jmp 0x2c1d
jmp 0x2c27
movq %rax, %rbx
movq 0xb0(%rsp), %rax
testq %rax, %rax
je 0x2cc5
leaq 0xa0(%rsp), %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
jmp 0x2cc5
movq %rax, %rdi
callq 0x33cf
jmp 0x2c27
movq %rax, %rbx
jmp 0x2cc5
movq %rax, %rbx
cmpl $0x1, %edx
jne 0x2cc5
movq %rbx, %rdi
callq 0x228d
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
jmp 0x2b0d
jmp 0x2c53
jmp 0x2c82
jmp 0x2c53
movq %rax, %rbx
jmp 0x2ccf
movq %rax, %rbx
movq 0xc0(%rsp), %rdi
leaq 0xd0(%rsp), %rax
cmpq %rax, %rdi
je 0x2ccf
movq 0xd0(%rsp), %rsi
incq %rsi
callq 0x2150
jmp 0x2ccf
movq %rax, %rbx
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0x2c9c
movq 0x20(%rsp), %rsi
subq %rdi, %rsi
callq 0x2150
movl $0x180, %r14d           # imm = 0x180
movq 0xc8(%rsp,%r14), %rdi
testq %rdi, %rdi
je 0x2cbf
movq 0xd8(%rsp,%r14), %rsi
subq %rdi, %rsi
callq 0x2150
addq $-0x18, %r14
jne 0x2ca2
leaq 0x50(%rsp), %rdi
callq 0x5236
movq 0x30(%rsp), %rdi
testq %rdi, %rdi
je 0x2ce6
movq 0x40(%rsp), %rsi
subq %rdi, %rsi
callq 0x2150
movq %rbx, %rdi
callq 0x2220