// File: 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:
subq $0x408, %rsp            # imm = 0x408
movl $0x0, 0x404(%rsp)
movl %edi, 0x400(%rsp)
movq %rsi, 0x3f8(%rsp)
cmpl $0x1, 0x400(%rsp)
jg 0x268e
movq 0x1797e(%rip), %rax     # 0x19fe0
movq (%rax), %rdi
movq 0x3f8(%rsp), %rax
movq (%rax), %rdx
leaq 0x10b89(%rip), %rsi     # 0x13200
movb $0x0, %al
callq 0x2290
movl $0xffffffff, 0x404(%rsp) # imm = 0xFFFFFFFF
jmp 0x3028
cmpl $0x2, 0x400(%rsp)
jne 0x26b0
movq 0x17941(%rip), %rax     # 0x19fe0
movq (%rax), %rdi
leaq 0x10b82(%rip), %rsi     # 0x1322b
movb $0x0, %al
callq 0x2290
jmp 0x26b2
leaq 0x3e0(%rsp), %rdi
callq 0x4750
movl $0x2, 0x3dc(%rsp)
movl 0x3dc(%rsp), %eax
cmpl 0x400(%rsp), %eax
jge 0x2846
movq 0x3f8(%rsp), %rax
movslq 0x3dc(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, 0x78(%rsp)
leaq 0x3b7(%rsp), %rdi
movq %rdi, 0x80(%rsp)
callq 0x2310
movq 0x78(%rsp), %rsi
movq 0x80(%rsp), %rdx
leaq 0x3b8(%rsp), %rdi
callq 0x4760
jmp 0x2728
leaq 0x3b8(%rsp), %rdi
callq 0x12ad0
movl %eax, 0x74(%rsp)
jmp 0x273b
leaq 0x3b8(%rsp), %rdi
callq 0x2100
leaq 0x3b7(%rsp), %rdi
callq 0x2200
movl 0x74(%rsp), %eax
movl %eax, 0x3d8(%rsp)
cmpl $0x0, 0x3d8(%rsp)
jge 0x27fe
movq 0x1786b(%rip), %rax     # 0x19fe0
movq (%rax), %rdi
movq 0x3f8(%rsp), %rax
movslq 0x3dc(%rsp), %rcx
movq (%rax,%rcx,8), %rdx
leaq 0x10ab5(%rip), %rsi     # 0x13248
movb $0x0, %al
callq 0x2290
movl $0xffffffff, 0x404(%rsp) # imm = 0xFFFFFFFF
movl $0x1, 0x3a0(%rsp)
jmp 0x300a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3a8(%rsp)
movl %eax, 0x3a4(%rsp)
jmp 0x27ec
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3a8(%rsp)
movl %eax, 0x3a4(%rsp)
leaq 0x3b8(%rsp), %rdi
callq 0x2100
leaq 0x3b7(%rsp), %rdi
callq 0x2200
jmp 0x3019
leaq 0x3e0(%rsp), %rdi
leaq 0x3d8(%rsp), %rsi
callq 0x4820
jmp 0x2815
jmp 0x2817
movl 0x3dc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3dc(%rsp)
jmp 0x26ca
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3a8(%rsp)
movl %eax, 0x3a4(%rsp)
jmp 0x3019
movq 0x3f8(%rsp), %rax
movq 0x8(%rax), %rdi
leaq 0x10a0a(%rip), %rsi     # 0x13263
callq 0x2240
movq %rax, 0x68(%rsp)
jmp 0x2865
movq 0x68(%rsp), %rax
movq %rax, 0x398(%rsp)
leaq 0x390(%rsp), %rdi
callq 0x9bd0
jmp 0x2881
movq 0x398(%rsp), %rsi
leaq 0x390(%rsp), %rdi
callq 0x9bf0
jmp 0x2898
jmp 0x2910
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3a8(%rsp)
movl %eax, 0x3a4(%rsp)
movl 0x3a4(%rsp), %eax
movl $0x1, %ecx
cmpl %ecx, %eax
jne 0x2ffb
movq 0x3a8(%rsp), %rdi
callq 0x2090
movl (%rax), %eax
movl %eax, 0x38c(%rsp)
movq 0x17701(%rip), %rax     # 0x19fe0
movq (%rax), %rdi
leaq 0x1097d(%rip), %rsi     # 0x13266
movb $0x0, %al
callq 0x2290
movl $0xffffffff, 0x404(%rsp) # imm = 0xFFFFFFFF
movl $0x1, 0x3a0(%rsp)
callq 0x22e0
jmp 0x2fec
movq 0x398(%rsp), %rdi
callq 0x21a0
jmp 0x291f
movl $0x20000, %edi          # imm = 0x20000
callq 0x2030
movq %rax, 0x60(%rsp)
jmp 0x2930
movq 0x60(%rsp), %rax
movq %rax, 0x380(%rsp)
movl $0x0, 0x37c(%rsp)
movq 0x380(%rsp), %rdi
xorl %esi, %esi
movl $0x20000, %edx          # imm = 0x20000
callq 0x20f0
leaq 0x390(%rsp), %rax
movq %rax, 0x340(%rsp)
leaq 0x380(%rsp), %rax
movq %rax, 0x348(%rsp)
leaq 0x37c(%rsp), %rax
movq %rax, 0x350(%rsp)
leaq 0x358(%rsp), %rdi
leaq 0x340(%rsp), %rsi
callq 0x3050
jmp 0x29a3
leaq 0x390(%rsp), %rdi
leaq 0x358(%rsp), %rsi
callq 0x2460
jmp 0x29ba
leaq 0x358(%rsp), %rdi
callq 0x4890
leaq 0x108ae(%rip), %rdi     # 0x1327c
leaq 0x108ad(%rip), %rsi     # 0x13282
callq 0x2240
movq %rax, 0x58(%rsp)
jmp 0x29e1
movq 0x58(%rsp), %rax
movq %rax, 0x398(%rsp)
leaq 0x390(%rsp), %rax
movq %rax, 0x308(%rsp)
leaq 0x398(%rsp), %rax
movq %rax, 0x310(%rsp)
leaq 0x380(%rsp), %rax
movq %rax, 0x318(%rsp)
leaq 0x320(%rsp), %rdi
leaq 0x308(%rsp), %rsi
callq 0x3100
jmp 0x2a35
leaq 0x390(%rsp), %rdi
leaq 0x320(%rsp), %rsi
callq 0x2460
jmp 0x2a4c
leaq 0x320(%rsp), %rdi
callq 0x4890
movq 0x398(%rsp), %rdi
movl $0xff, %esi
callq 0x2590
jmp 0x2a6d
leaq 0x180(%rsp), %rax
movq %rax, %rcx
addq $0x180, %rcx            # imm = 0x180
movq %rcx, 0x48(%rsp)
movq %rax, 0x50(%rsp)
movq 0x50(%rsp), %rdi
movq %rdi, 0x40(%rsp)
callq 0x48a0
movq 0x40(%rsp), %rax
movq 0x48(%rsp), %rcx
addq $0x18, %rax
cmpq %rcx, %rax
movq %rax, 0x50(%rsp)
jne 0x2a89
leaq 0x168(%rsp), %rdi
movq %rdi, 0x38(%rsp)
callq 0x48a0
movq 0x38(%rsp), %rax
leaq 0x390(%rsp), %rcx
movq %rcx, 0x130(%rsp)
leaq 0x180(%rsp), %rcx
movq %rcx, 0x138(%rsp)
movq %rax, 0x140(%rsp)
leaq 0x148(%rsp), %rdi
leaq 0x130(%rsp), %rsi
callq 0x31b0
jmp 0x2b06
leaq 0x390(%rsp), %rdi
leaq 0x148(%rsp), %rsi
callq 0x2460
jmp 0x2b1d
leaq 0x148(%rsp), %rdi
callq 0x4890
movl $0x0, 0x12c(%rsp)
cmpl $0x10, 0x12c(%rsp)
jge 0x2c55
movslq 0x12c(%rsp), %rax
leaq (%rax,%rax,2), %rax
leaq 0x180(%rsp,%rax,8), %rdi
callq 0x48f0
movq %rax, 0x120(%rsp)
movslq 0x12c(%rsp), %rax
leaq (%rax,%rax,2), %rax
leaq 0x180(%rsp,%rax,8), %rdi
callq 0x4920
movq %rax, 0x118(%rsp)
movq 0x120(%rsp), %rdi
movq 0x118(%rsp), %rsi
callq 0x48b0
jmp 0x2b9c
jmp 0x2b9e
movl 0x12c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x12c(%rsp)
jmp 0x2b35
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3a8(%rsp)
movl %eax, 0x3a4(%rsp)
jmp 0x2ffb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3a8(%rsp)
movl %eax, 0x3a4(%rsp)
leaq 0x358(%rsp), %rdi
callq 0x4890
jmp 0x2ffb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3a8(%rsp)
movl %eax, 0x3a4(%rsp)
leaq 0x320(%rsp), %rdi
callq 0x4890
jmp 0x2ffb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3a8(%rsp)
movl %eax, 0x3a4(%rsp)
jmp 0x2f75
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3a8(%rsp)
movl %eax, 0x3a4(%rsp)
leaq 0x148(%rsp), %rdi
callq 0x4890
jmp 0x2f75
leaq 0x168(%rsp), %rdi
movq %rdi, 0x30(%rsp)
callq 0x48f0
movq 0x30(%rsp), %rdi
movq %rax, 0x110(%rsp)
callq 0x4920
movq %rax, 0x108(%rsp)
movq 0x110(%rsp), %rdi
movq 0x108(%rsp), %rsi
callq 0x48b0
jmp 0x2c98
leaq 0x3e0(%rsp), %rax
movq %rax, 0x100(%rsp)
movq 0x100(%rsp), %rdi
callq 0x4950
movq %rax, 0xf8(%rsp)
movq 0x100(%rsp), %rdi
callq 0x4980
movq %rax, 0xf0(%rsp)
leaq 0xf8(%rsp), %rdi
leaq 0xf0(%rsp), %rsi
callq 0x49b0
testb $0x1, %al
jne 0x2cf0
jmp 0x2e20
leaq 0xf8(%rsp), %rdi
callq 0x49f0
movq %rax, 0xe8(%rsp)
movq 0xe8(%rsp), %rax
movslq (%rax), %rcx
leaq 0x180(%rsp), %rax
imulq $0x18, %rcx, %rcx
addq %rcx, %rax
movq %rax, 0xe0(%rsp)
movq 0xe0(%rsp), %rdi
callq 0x48f0
movq %rax, 0xd8(%rsp)
movq 0xe0(%rsp), %rdi
callq 0x4920
movq %rax, 0xd0(%rsp)
leaq 0xd8(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
callq 0x4a00
testb $0x1, %al
jne 0x2d6f
jmp 0x2df8
leaq 0xd8(%rsp), %rdi
callq 0x4a40
movq %rax, 0xc8(%rsp)
movq 0xc8(%rsp), %rdi
callq 0x4a50
movq %rax, 0xc0(%rsp)
movq 0xc8(%rsp), %rdi
callq 0x4a60
movq %rax, 0xb8(%rsp)
movq 0x398(%rsp), %rdi
movq 0x380(%rsp), %rax
movq 0xb8(%rsp), %rcx
movl (%rcx), %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 0x25c0
jmp 0x2de4
jmp 0x2de6
leaq 0xd8(%rsp), %rdi
callq 0x4a70
jmp 0x2d51
movq 0x398(%rsp), %rdi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x25c0
jmp 0x2e0c
jmp 0x2e0e
leaq 0xf8(%rsp), %rdi
callq 0x4a90
jmp 0x2cd2
movq 0x398(%rsp), %rdi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x25c0
jmp 0x2e34
leaq 0x168(%rsp), %rax
movq %rax, 0xb0(%rsp)
movq 0xb0(%rsp), %rdi
callq 0x48f0
movq %rax, 0xa8(%rsp)
movq 0xb0(%rsp), %rdi
callq 0x4920
movq %rax, 0xa0(%rsp)
leaq 0xa8(%rsp), %rdi
leaq 0xa0(%rsp), %rsi
callq 0x4a00
testb $0x1, %al
jne 0x2e8c
jmp 0x2f15
leaq 0xa8(%rsp), %rdi
callq 0x4a40
movq %rax, 0x98(%rsp)
movq 0x98(%rsp), %rdi
callq 0x4a50
movq %rax, 0x90(%rsp)
movq 0x98(%rsp), %rdi
callq 0x4a60
movq %rax, 0x88(%rsp)
movq 0x398(%rsp), %rdi
movq 0x380(%rsp), %rax
movq 0x88(%rsp), %rcx
movl (%rcx), %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 0x25c0
jmp 0x2f01
jmp 0x2f03
leaq 0xa8(%rsp), %rdi
callq 0x4a70
jmp 0x2e6e
movq 0x398(%rsp), %rdi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x25c0
jmp 0x2f29
movq 0x398(%rsp), %rdi
callq 0x21a0
jmp 0x2f38
movl $0x0, 0x404(%rsp)
movl $0x1, 0x3a0(%rsp)
leaq 0x168(%rsp), %rdi
callq 0x4ab0
leaq 0x180(%rsp), %rax
movq %rax, 0x20(%rsp)
addq $0x180, %rax            # imm = 0x180
movq %rax, 0x28(%rsp)
jmp 0x2f9c
leaq 0x168(%rsp), %rdi
callq 0x4ab0
leaq 0x180(%rsp), %rax
movq %rax, 0x10(%rsp)
addq $0x180, %rax            # imm = 0x180
movq %rax, 0x18(%rsp)
jmp 0x2fc5
movq 0x28(%rsp), %rdi
addq $-0x18, %rdi
movq %rdi, 0x8(%rsp)
callq 0x4ab0
movq 0x20(%rsp), %rcx
movq 0x8(%rsp), %rax
cmpq %rcx, %rax
movq %rax, 0x28(%rsp)
jne 0x2f9c
jmp 0x2fec
movq 0x18(%rsp), %rdi
addq $-0x18, %rdi
movq %rdi, (%rsp)
callq 0x4ab0
movq 0x10(%rsp), %rcx
movq (%rsp), %rax
cmpq %rcx, %rax
movq %rax, 0x18(%rsp)
jne 0x2fc5
jmp 0x2ffb
leaq 0x390(%rsp), %rdi
callq 0xa200
jmp 0x300a
leaq 0x390(%rsp), %rdi
callq 0xa200
jmp 0x3019
leaq 0x3e0(%rsp), %rdi
callq 0x4b10
jmp 0x3028
leaq 0x3e0(%rsp), %rdi
callq 0x4b10
jmp 0x3037
movl 0x404(%rsp), %eax
addq $0x408, %rsp            # imm = 0x408
retq
movq 0x3a8(%rsp), %rdi
callq 0x2300
nopw %cs:(%rax,%rax)