// File: TNanukem[P]chip8-emulator/chip8.cpp
// Function: chip8::nextCycle()
void chip8::nextCycle(){

	// Fetching the instruction
	opcode = memory[pc] << 8 | memory[pc+1];

	// Decoding the instruction
	switch(opcode & GET_4BITS){					// Decode the instruction based on the first 4 bits

		// Decodification of the 0x0 opcodes
		case 0x0000:
			switch(opcode & GET_8BIT_CONSTANT){

				// Clears the screen.
				case 0x00E0:
					for(int i = 0; i < 32*64; i++){
						display[i] = 0;
					}
					pc += 2;
					drawFlag = 1;
                    //printf("CLS\n");
					break;

				// Returns from a subroutine.
				case 0x00EE:
					sp--;
					pc = stack[sp];
                    pc += 2;
                    //printf("RET\n");
					break;
			}
			break;

		// Jumps to the address NNN
		case 0x1000:
			pc = (opcode & GET_ADDRESS);
            //printf("JMP %d\n", opcode & GET_ADDRESS);
			break;

        // Calls subroutine at NNN.
		case 0x2000:
			stack[sp] = pc;
			sp++;
			pc = opcode & GET_ADDRESS;
            //printf("CALL %d\n", opcode & GET_ADDRESS);
			break;

		// Skips the next instruction if v[X] is equal to NN
		case 0x3000:
			if(v[(opcode & GET_X) >> 8] == (opcode & GET_8BIT_CONSTANT))
					pc += 4;
			else
                pc += 2;
            //printf("SE V%d,%d\n", (opcode & GET_X) >> 8, opcode & GET_8BIT_CONSTANT);
			break;

		// Skips the next instruction if v[X] is not equal to NN
		case 0x4000:
			if(v[(opcode & GET_X) >> 8] != (opcode & GET_8BIT_CONSTANT))
				pc += 4;
			else
                pc += 2;
            //printf("SNE V%d,%d\n", (opcode & GET_X) >> 8, opcode & GET_8BIT_CONSTANT);
			break;

		// Skips the next instruction if v[X] is equal to v[Y]
		case 0x5000:
			if(v[(opcode & GET_X) >> 8] == v[(opcode & GET_Y) >> 4]){
				pc += 4;
			}
			else
				pc += 2;

            //printf("SE V%d,V%d\n", (opcode & GET_X) >> 8, (opcode & GET_Y) >> 4);
			break;

		// Sets v[X] to NN
		case 0x6000:
			v[(opcode & GET_X) >> 8] = (opcode & GET_8BIT_CONSTANT);
			pc += 2;
            //printf("LD V%d,%d\n", (opcode & GET_X) >> 8, opcode & GET_8BIT_CONSTANT);
			break;

		// Adds NN to v[X]
		case 0x7000:
			v[(opcode & GET_X) >> 8]  += (opcode & GET_8BIT_CONSTANT);
			pc += 2;
            //printf("ADD V%d,%d\n", (opcode & GET_X) >> 8, opcode & GET_8BIT_CONSTANT);
			break;

		// Skips the next instruction if v[X] is not equal to v[Y]
		case 0x9000:
			if(v[opcode & GET_X >> 8] != v[(opcode & GET_Y) >> 4]){
				pc += 4;
			}
			else pc += 2;
            //printf("SNE V%d,V%d\n", (opcode & GET_X) >> 8, (opcode & GET_Y) >> 4);
			break;

		case 0x8000:
			switch(opcode & GET_4BIT_CONSTANT){

				// Sets v[X] to v[Y]
				case 0x0000:
					v[(opcode & GET_X) >> 8] = v[(opcode & GET_Y) >> 4];
					pc += 2;
                    //printf("LD V%d,V%d\n", (opcode & GET_X) >> 8, (opcode & GET_Y) >> 4);
					break;

				// Sets v[X] to v[X] OR v[Y]
				case 0x0001:
					v[(opcode & GET_X) >> 8] |= v[(opcode & GET_Y) >> 4];
					pc += 2;
                    //printf("OR V%d,V%d\n", (opcode & GET_X) >> 8, (opcode & GET_Y) >> 4);
					break;

				// Sets v[X] to v[X] AND v[Y]
				case 0x0002:
					v[(opcode & GET_X) >> 8] &= v[(opcode & GET_Y) >> 4];
					pc += 2;
                    //printf("AND V%d,V%d\n", (opcode & GET_X) >> 8, (opcode & GET_Y) >> 4);
					break;

				// Sets v[X] to v[X] XOR v[Y]
				case 0x0003:
					v[(opcode & GET_X) >> 8] ^= v[(opcode & GET_Y) >> 4];
					pc += 2;
                    //printf("XOR V%d,V%d\n", (opcode & GET_X) >> 8, (opcode & GET_Y) >> 4);
					break;

				// Adds VY to VX. VF is set to 1 when there's a carry, and to 0 when there isn't.
				case 0x0004:
					if(v[(opcode & GET_Y) >> 4] > (0xFF - v[(opcode & GET_X) >> 8]))
						v[0xF] = 1;
					else
						v[0xF] = 0;
					v[(opcode & GET_X) >> 8] += v[(opcode & GET_Y) >> 4];
					pc += 2;
                    //printf("ADD V%d,V%d\n", (opcode & GET_X) >> 8, (opcode & GET_Y) >> 4);
					break;

				// VY is subtracted from VX. VF is set to 0 when there's a borrow, and 1 when there isn't.
				case 0x0005:
					if(v[(opcode & GET_X) >> 8] > v[(opcode & GET_Y) >> 4])
						v[0xF] = 1;
					else
						v[0xF] = 0;
					v[(opcode & GET_X) >> 8] -= v[(opcode & GET_Y) >> 4];
					pc += 2;
                    //printf("SUB V%d,V%d\n", (opcode & GET_X) >> 8, (opcode & GET_Y) >> 4);
					break;

				// Stores the least significant bit of VX in VF and then shifts VX to the right by 1.
				case 0x0006:
					if((v[(opcode & GET_X) >> 8] & 0x01) == 0x01)
                        v[0xF] = 1;
                    else
                        v[0xF] = 0;
                    pc += 2;
                    v[(opcode & GET_X) >> 8] = v[(opcode & GET_X) >> 8]/2;
                    //printf("SHR V%d,V%d\n", (opcode & GET_X) >> 8, (opcode & GET_Y) >> 4);
					break;

				// Sets VX to VY minus VX. VF is set to 0 when there's a borrow, and 1 when there isn't.
				case 0x0007:
					if(v[(opcode & GET_Y) >> 4] > v[(opcode & GET_X) >> 8])
						v[0xF] = 1;
					else
						v[0xF] = 0;
					v[(opcode & GET_X) >> 8] = v[(opcode & GET_Y) >> 4] - v[(opcode & GET_X) >> 8];
					pc += 2;
                    //printf("SUBN V%d,V%d\n", (opcode & GET_X) >> 8, (opcode & GET_Y) >> 4);
					break;

				// Stores the most significant bit of VX in VF and then shifts VX to the left by 1.
				case 0x000E:
                    if((v[(opcode & GET_X) >> 8] & 0x80) == 0x80)
                        v[0xF] = 1;
                    else
                        v[0xF] = 0;
					pc += 2;
                    v[(opcode & GET_X) >> 8] = v[(opcode & GET_X) >> 8]*2;
                    //printf("SHL V%d,V%d\n", (opcode & GET_X) >> 8, (opcode & GET_Y) >> 4);
					break;
			}
			break;

		// Sets the I address to NNN
		case 0xA000:
			I = opcode & GET_ADDRESS;
			pc += 2;
            //printf("LD I, %d\n", opcode & GET_ADDRESS);
			break;

		// Jumps to the address V0 + NNN
		case 0xB000:
			pc = (opcode & GET_ADDRESS) + v[0];
            //printf("JP V0,%d\n", opcode & GET_ADDRESS);
			break;

		// Sets VX to the result of a bitwise and operation on a random number (Typically: 0 to 255) and NN.
		case 0xC000:
			v[opcode & GET_X >> 8] = (rand() % 255) & (opcode & GET_8BIT_CONSTANT);
			pc += 2;
            //printf("RND V%d,%d\n", (opcode & GET_X) >> 8, opcode & GET_8BIT_CONSTANT);
			break;

		// Draws a sprite at (vx,vy) with size height of N pixels
		case 0xD000:
            xaux = v[(opcode & GET_X) >> 8];
            yaux = v[(opcode & GET_Y) >> 4];
            height = opcode & GET_4BIT_CONSTANT;

            v[0xF] = 0;         // Resets the VF

            for(int y = 0; y < height; y++){              // Passes through all lines of the sprite
                pixel = memory[I + y];      // Fetches the pixel value on the memory
                for(int x = 0; x < 8; x++){             // Passes through all 8 columns of the sprite, in each line
                    if((pixel & (0x80 >> x)) != 0){
                        if(display[(xaux + x + ((yaux + y)*64))] == 1)
                            v[0xF] = 1;                 // Registers the collision
                        display[(xaux + x + ((yaux + y)*64))] ^= 1;
                    }
                }
            }

            drawFlag = true;
			pc += 2;
            //printf("DRW V%d,V%d,%d\n", (opcode & GET_X) >> 8, (opcode & GET_Y) >> 4, opcode & GET_4BIT_CONSTANT);
			break;

		case 0xE000:
			switch(opcode & GET_4BIT_CONSTANT){

				// Skips the next instruction if the key stored in VX is pressed.
				case 0x000E:
                    //printf("SKP V%d\n", (opcode & GET_X) >> 8);
					if(keyboard[v[(opcode & GET_X) >> 8]] != 0)
						pc += 4;
					else
						pc += 2;
					break;

				// Skips the next instruction if the key stored in VX isn't pressed.
				case 0x0001:
                    //printf("SKNP V%d\n", (opcode & GET_X) >> 8);
					if(keyboard[v[(opcode & GET_X) >> 8]] == 0)
						pc += 4;
					else
						pc += 2;
					break;
			}

			break;

		case 0xF000:
            switch(opcode & GET_8BIT_CONSTANT){
				// Sets VX to the value of the delay timer.
				case 0x0007:
					v[(opcode & GET_X) >> 8] = delayTimer;
					pc += 2;
                    //printf("LD V%d, DT\n", (opcode & GET_X) >> 8);
					break;

                // A key press is awaited, and then stored in VX
				case 0x000A:
                    //printf("KEYWAIT V%d, K\n", (opcode & GET_X) >> 8);
					pressedKey = false;
                    while(!pressedKey){
    					for(int i = 0; i < 16; i++){
    						if(keyboard[i] != 0){
    							v[(opcode & GET_X) >> 8] = i;
    							pressedKey = true;
                                break;
    						}
                        }
                    }
						pc += 2;
                        break;

				// Sets the delay timer to the value of v[X]
				case 0x0015:
                    //printf("LD DT, V%d\n", (opcode & GET_X) >> 8);
					delayTimer = v[(opcode & GET_X) >> 8];
					pc += 2;
					break;

				// Sets the sound timer to the value of v[X]
				case 0x0018:
                    //printf("LD ST, V%d\n", (opcode & GET_X) >> 8);
					soundTimer = v[(opcode & GET_X) >> 8];
					pc += 2;
					break;

				// Adds v[X] to I
				case 0x001E:
                    //printf("ADD I, V%d\n", (opcode & GET_X) >> 8);
                    if((I + v[(opcode & GET_X) >> 8]) > 0xFFFF)
                        v[0xF] = 1;
                    else
                        v[0xF] = 0;

                    I += v[(opcode & GET_X) >> 8];
					pc += 2;
					break;

				// Sets I to the location of the sprite for the character in VX.
				case 0x0029:
                    //printf("LD F, V%d\n", (opcode & GET_X) >> 8);
					I = v[(opcode & GET_X) >> 8] * 0x5;
					pc += 2;
					break;

				// Stores the Binary-coded decimal representation of VX at the addresses I, I plus 1, and I plus 2
				// Implementation by TJA
				case 0x0033:
                    //printf("LD B, V%d\n", (opcode & GET_X) >> 8);
					memory[I]     = v[(opcode & 0x0F00) >> 8] / 100;
					memory[I + 1] = (v[(opcode & 0x0F00) >> 8] / 10) % 10;
					memory[I + 2] = (v[(opcode & 0x0F00) >> 8] % 100) % 10;
					pc += 2;
					break;

				//Stores V0 to VX (including VX) in memory starting at address I.
				case 0x0055:
                    //printf("LD [I], V%d\n", (opcode & GET_X) >> 8);
					for(int i = 0; i <= ((opcode & GET_X) >> 8); i++){
						memory[I+i] = v[i];
					}
                    I += ((opcode & GET_X) >> 8) + 1;
					pc += 2;
					break;

				// Fills V0 to VX (including VX) with values from memory starting at address I.
				case 0x0065:
                    //printf("I = %d\n", I);
                    //printf("LD V%d, [I]\n", (opcode & GET_X) >> 8);
					for(int i = 0; i <= ((opcode & GET_X) >> 8) ; i++){
                        v[i] = memory[I+i];
					}
                    I += ((opcode & GET_X) >> 8) + 1;
					pc += 2;
					break;
			}
        break;

        default:
            //printf("ERROR! Opcode not known!\n");
            break;
	}

	// Decrement the timers if they are greater than zero
	if(delayTimer > 0)
		delayTimer--;

	if(soundTimer > 0)
        if(soundTimer == 1){
            playSound = true;
            //printf("BEEP\n");
        }
		soundTimer--;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x30(%rbp)
movzwl 0x1014(%rax), %ecx
movl %ecx, %edx
movzbl 0x2(%rax,%rdx), %ecx
shll $0x8, %ecx
movzbl 0x3(%rax,%rdx), %edx
orl %edx, %ecx
movw %cx, (%rax)
movzwl (%rax), %eax
andl $0xf000, %eax           # imm = 0xF000
movl %eax, -0x24(%rbp)
je 0x29a5
jmp 0x28b2
movl -0x24(%rbp), %eax
subl $0x1000, %eax           # imm = 0x1000
je 0x2a55
jmp 0x28c2
movl -0x24(%rbp), %eax
subl $0x2000, %eax           # imm = 0x2000
je 0x2a6e
jmp 0x28d2
movl -0x24(%rbp), %eax
subl $0x3000, %eax           # imm = 0x3000
je 0x2aaf
jmp 0x28e2
movl -0x24(%rbp), %eax
subl $0x4000, %eax           # imm = 0x4000
je 0x2b06
jmp 0x28f2
movl -0x24(%rbp), %eax
subl $0x5000, %eax           # imm = 0x5000
je 0x2b5d
jmp 0x2902
movl -0x24(%rbp), %eax
subl $0x6000, %eax           # imm = 0x6000
je 0x2bc2
jmp 0x2912
movl -0x24(%rbp), %eax
subl $0x7000, %eax           # imm = 0x7000
je 0x2bfd
jmp 0x2922
movl -0x24(%rbp), %eax
subl $0x8000, %eax           # imm = 0x8000
je 0x2ca0
jmp 0x2932
movl -0x24(%rbp), %eax
subl $0x9000, %eax           # imm = 0x9000
je 0x2c40
jmp 0x2942
movl -0x24(%rbp), %eax
subl $0xa000, %eax           # imm = 0xA000
je 0x3111
jmp 0x2952
movl -0x24(%rbp), %eax
subl $0xb000, %eax           # imm = 0xB000
je 0x313b
jmp 0x2962
movl -0x24(%rbp), %eax
subl $0xc000, %eax           # imm = 0xC000
je 0x315d
jmp 0x2972
movl -0x24(%rbp), %eax
subl $0xd000, %eax           # imm = 0xD000
je 0x319f
jmp 0x2982
movl -0x24(%rbp), %eax
subl $0xe000, %eax           # imm = 0xE000
je 0x32f7
jmp 0x2992
movl -0x24(%rbp), %eax
subl $0xf000, %eax           # imm = 0xF000
je 0x33ca
jmp 0x37fb
movq -0x30(%rbp), %rax
movzbl (%rax), %eax
movl %eax, -0x34(%rbp)
subl $0xe0, %eax
je 0x29c7
jmp 0x29b8
movl -0x34(%rbp), %eax
subl $0xee, %eax
je 0x2a13
jmp 0x2a50
movl $0x0, -0xc(%rbp)
cmpl $0x800, -0xc(%rbp)      # imm = 0x800
jge 0x29f5
movq -0x30(%rbp), %rax
movslq -0xc(%rbp), %rcx
movl $0x0, 0x1018(%rax,%rcx,4)
movl -0xc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xc(%rbp)
jmp 0x29ce
movq -0x30(%rbp), %rax
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
movb $0x1, 0x304c(%rax)
jmp 0x2a50
movq -0x30(%rbp), %rax
movw 0x303a(%rax), %cx
addw $-0x1, %cx
movw %cx, 0x303a(%rax)
movzwl 0x303a(%rax), %ecx
movw 0x301a(%rax,%rcx,2), %cx
movw %cx, 0x1014(%rax)
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x37fd
movq -0x30(%rbp), %rax
movzwl (%rax), %ecx
andl $0xfff, %ecx            # imm = 0xFFF
movw %cx, 0x1014(%rax)
jmp 0x37fd
movq -0x30(%rbp), %rax
movw 0x1014(%rax), %dx
movzwl 0x303a(%rax), %ecx
movw %dx, 0x301a(%rax,%rcx,2)
movw 0x303a(%rax), %cx
addw $0x1, %cx
movw %cx, 0x303a(%rax)
movzwl (%rax), %ecx
andl $0xfff, %ecx            # imm = 0xFFF
movw %cx, 0x1014(%rax)
jmp 0x37fd
movq -0x30(%rbp), %rcx
movzwl (%rcx), %eax
andl $0xf00, %eax            # imm = 0xF00
sarl $0x8, %eax
cltq
movzbl 0x1002(%rcx,%rax), %eax
movzwl (%rcx), %ecx
andl $0xff, %ecx
cmpl %ecx, %eax
jne 0x2aec
movq -0x30(%rbp), %rax
movzwl 0x1014(%rax), %ecx
addl $0x4, %ecx
movw %cx, 0x1014(%rax)
jmp 0x2b01
movq -0x30(%rbp), %rax
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x37fd
movq -0x30(%rbp), %rcx
movzwl (%rcx), %eax
andl $0xf00, %eax            # imm = 0xF00
sarl $0x8, %eax
cltq
movzbl 0x1002(%rcx,%rax), %eax
movzwl (%rcx), %ecx
andl $0xff, %ecx
cmpl %ecx, %eax
je 0x2b43
movq -0x30(%rbp), %rax
movzwl 0x1014(%rax), %ecx
addl $0x4, %ecx
movw %cx, 0x1014(%rax)
jmp 0x2b58
movq -0x30(%rbp), %rax
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x37fd
movq -0x30(%rbp), %rcx
movzwl (%rcx), %eax
andl $0xf00, %eax            # imm = 0xF00
sarl $0x8, %eax
cltq
movzbl 0x1002(%rcx,%rax), %eax
movzwl (%rcx), %edx
andl $0xf0, %edx
sarl $0x4, %edx
movslq %edx, %rdx
movzbl 0x1002(%rcx,%rdx), %ecx
cmpl %ecx, %eax
jne 0x2ba8
movq -0x30(%rbp), %rax
movzwl 0x1014(%rax), %ecx
addl $0x4, %ecx
movw %cx, 0x1014(%rax)
jmp 0x2bbd
movq -0x30(%rbp), %rax
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x37fd
movq -0x30(%rbp), %rax
movzwl (%rax), %ecx
andl $0xff, %ecx
movb %cl, %dl
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movb %dl, 0x1002(%rax,%rcx)
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x37fd
movq -0x30(%rbp), %rax
movzwl (%rax), %esi
andl $0xff, %esi
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1002(%rax,%rcx), %edx
addl %esi, %edx
movb %dl, 0x1002(%rax,%rcx)
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x37fd
movq -0x30(%rbp), %rcx
movzwl (%rcx), %eax
andl $0xf, %eax
cltq
movzbl 0x1002(%rcx,%rax), %eax
movzwl (%rcx), %edx
andl $0xf0, %edx
sarl $0x4, %edx
movslq %edx, %rdx
movzbl 0x1002(%rcx,%rdx), %ecx
cmpl %ecx, %eax
je 0x2c86
movq -0x30(%rbp), %rax
movzwl 0x1014(%rax), %ecx
addl $0x4, %ecx
movw %cx, 0x1014(%rax)
jmp 0x2c9b
movq -0x30(%rbp), %rax
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x37fd
movq -0x30(%rbp), %rax
movzwl (%rax), %eax
andl $0xf, %eax
movl %eax, %ecx
movq %rcx, -0x40(%rbp)
subl $0xe, %eax
ja 0x310c
movq -0x40(%rbp), %rax
leaq 0x3340(%rip), %rcx      # 0x6004
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x30(%rbp), %rax
movzwl (%rax), %ecx
andl $0xf0, %ecx
sarl $0x4, %ecx
movslq %ecx, %rcx
movb 0x1002(%rax,%rcx), %dl
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movb %dl, 0x1002(%rax,%rcx)
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x310c
movq -0x30(%rbp), %rax
movzwl (%rax), %ecx
andl $0xf0, %ecx
sarl $0x4, %ecx
movslq %ecx, %rcx
movzbl 0x1002(%rax,%rcx), %esi
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1002(%rax,%rcx), %edx
orl %esi, %edx
movb %dl, 0x1002(%rax,%rcx)
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x310c
movq -0x30(%rbp), %rax
movzwl (%rax), %ecx
andl $0xf0, %ecx
sarl $0x4, %ecx
movslq %ecx, %rcx
movzbl 0x1002(%rax,%rcx), %esi
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1002(%rax,%rcx), %edx
andl %esi, %edx
movb %dl, 0x1002(%rax,%rcx)
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x310c
movq -0x30(%rbp), %rax
movzwl (%rax), %ecx
andl $0xf0, %ecx
sarl $0x4, %ecx
movslq %ecx, %rcx
movzbl 0x1002(%rax,%rcx), %esi
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1002(%rax,%rcx), %edx
xorl %esi, %edx
movb %dl, 0x1002(%rax,%rcx)
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x310c
movq -0x30(%rbp), %rcx
movzwl (%rcx), %eax
andl $0xf0, %eax
sarl $0x4, %eax
cltq
movzbl 0x1002(%rcx,%rax), %eax
movzwl (%rcx), %edx
andl $0xf00, %edx            # imm = 0xF00
sarl $0x8, %edx
movslq %edx, %rdx
movzbl 0x1002(%rcx,%rdx), %edx
movl $0xff, %ecx
subl %edx, %ecx
cmpl %ecx, %eax
jle 0x2e4e
movq -0x30(%rbp), %rax
movb $0x1, 0x1011(%rax)
jmp 0x2e59
movq -0x30(%rbp), %rax
movb $0x0, 0x1011(%rax)
movq -0x30(%rbp), %rax
movzwl (%rax), %ecx
andl $0xf0, %ecx
sarl $0x4, %ecx
movslq %ecx, %rcx
movzbl 0x1002(%rax,%rcx), %esi
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1002(%rax,%rcx), %edx
addl %esi, %edx
movb %dl, 0x1002(%rax,%rcx)
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x310c
movq -0x30(%rbp), %rcx
movzwl (%rcx), %eax
andl $0xf00, %eax            # imm = 0xF00
sarl $0x8, %eax
cltq
movzbl 0x1002(%rcx,%rax), %eax
movzwl (%rcx), %edx
andl $0xf0, %edx
sarl $0x4, %edx
movslq %edx, %rdx
movzbl 0x1002(%rcx,%rdx), %ecx
cmpl %ecx, %eax
jle 0x2eeb
movq -0x30(%rbp), %rax
movb $0x1, 0x1011(%rax)
jmp 0x2ef6
movq -0x30(%rbp), %rax
movb $0x0, 0x1011(%rax)
movq -0x30(%rbp), %rax
movzwl (%rax), %ecx
andl $0xf0, %ecx
sarl $0x4, %ecx
movslq %ecx, %rcx
movzbl 0x1002(%rax,%rcx), %esi
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1002(%rax,%rcx), %edx
subl %esi, %edx
movb %dl, 0x1002(%rax,%rcx)
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x310c
movq -0x30(%rbp), %rax
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1002(%rax,%rcx), %eax
andl $0x1, %eax
cmpl $0x1, %eax
jne 0x2f77
movq -0x30(%rbp), %rax
movb $0x1, 0x1011(%rax)
jmp 0x2f82
movq -0x30(%rbp), %rax
movb $0x0, 0x1011(%rax)
movq -0x30(%rbp), %rax
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1002(%rax,%rcx), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movq -0x30(%rbp), %rax
movb %cl, %dl
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movb %dl, 0x1002(%rax,%rcx)
jmp 0x310c
movq -0x30(%rbp), %rcx
movzwl (%rcx), %eax
andl $0xf0, %eax
sarl $0x4, %eax
cltq
movzbl 0x1002(%rcx,%rax), %eax
movzwl (%rcx), %edx
andl $0xf00, %edx            # imm = 0xF00
sarl $0x8, %edx
movslq %edx, %rdx
movzbl 0x1002(%rcx,%rdx), %ecx
cmpl %ecx, %eax
jle 0x301a
movq -0x30(%rbp), %rax
movb $0x1, 0x1011(%rax)
jmp 0x3025
movq -0x30(%rbp), %rax
movb $0x0, 0x1011(%rax)
movq -0x30(%rbp), %rax
movzwl (%rax), %ecx
andl $0xf0, %ecx
sarl $0x4, %ecx
movslq %ecx, %rcx
movzbl 0x1002(%rax,%rcx), %ecx
movzwl (%rax), %edx
andl $0xf00, %edx            # imm = 0xF00
sarl $0x8, %edx
movslq %edx, %rdx
movzbl 0x1002(%rax,%rdx), %edx
subl %edx, %ecx
movb %cl, %dl
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movb %dl, 0x1002(%rax,%rcx)
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x310c
movq -0x30(%rbp), %rax
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1002(%rax,%rcx), %eax
andl $0x80, %eax
cmpl $0x80, %eax
jne 0x30bb
movq -0x30(%rbp), %rax
movb $0x1, 0x1011(%rax)
jmp 0x30c6
movq -0x30(%rbp), %rax
movb $0x0, 0x1011(%rax)
movq -0x30(%rbp), %rax
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1002(%rax,%rcx), %ecx
shll %ecx
movb %cl, %dl
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movb %dl, 0x1002(%rax,%rcx)
jmp 0x37fd
movq -0x30(%rbp), %rax
movzwl (%rax), %ecx
andl $0xfff, %ecx            # imm = 0xFFF
movw %cx, 0x1012(%rax)
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x37fd
movq -0x30(%rbp), %rax
movzwl (%rax), %ecx
andl $0xfff, %ecx            # imm = 0xFFF
movzbl 0x1002(%rax), %edx
addl %edx, %ecx
movw %cx, 0x1014(%rax)
jmp 0x37fd
callq 0x20d0
movl $0xff, %ecx
cltd
idivl %ecx
movq -0x30(%rbp), %rax
movzwl (%rax), %ecx
andl $0xff, %ecx
andl %ecx, %edx
movzwl (%rax), %ecx
andl $0xf, %ecx
movslq %ecx, %rcx
movb %dl, 0x1002(%rax,%rcx)
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x37fd
movq -0x30(%rbp), %rax
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1002(%rax,%rcx), %ecx
movw %cx, 0x60ef(%rip)       # 0x92b0
movzwl (%rax), %ecx
andl $0xf0, %ecx
sarl $0x4, %ecx
movslq %ecx, %rcx
movzbl 0x1002(%rax,%rcx), %ecx
movw %cx, 0x60d3(%rip)       # 0x92b2
movzwl (%rax), %ecx
andl $0xf, %ecx
movl %ecx, 0x60c9(%rip)      # 0x92b4
movb $0x0, 0x1011(%rax)
movl $0x0, -0x10(%rbp)
movl -0x10(%rbp), %eax
cmpl 0x60b2(%rip), %eax      # 0x92b4
jge 0x32d6
movq -0x30(%rbp), %rax
movzwl 0x1012(%rax), %ecx
addl -0x10(%rbp), %ecx
movslq %ecx, %rcx
movzbl 0x2(%rax,%rcx), %eax
movw %ax, 0x6089(%rip)       # 0x92ae
movl $0x0, -0x14(%rbp)
cmpl $0x8, -0x14(%rbp)
jge 0x32c6
movzwl 0x6071(%rip), %eax      # 0x92ae
movl -0x14(%rbp), %ecx
movl $0x80, %edx
sarl %cl, %edx
movl %edx, %ecx
andl %ecx, %eax
cmpl $0x0, %eax
je 0x32b6
movq -0x30(%rbp), %rax
movzwl 0x6055(%rip), %ecx      # 0x92b0
addl -0x14(%rbp), %ecx
movzwl 0x604d(%rip), %edx      # 0x92b2
addl -0x10(%rbp), %edx
shll $0x6, %edx
addl %edx, %ecx
movslq %ecx, %rcx
cmpl $0x1, 0x1018(%rax,%rcx,4)
jne 0x3285
movq -0x30(%rbp), %rax
movb $0x1, 0x1011(%rax)
movq -0x30(%rbp), %rax
movzwl 0x6020(%rip), %ecx      # 0x92b0
addl -0x14(%rbp), %ecx
movzwl 0x6018(%rip), %edx      # 0x92b2
addl -0x10(%rbp), %edx
shll $0x6, %edx
addl %edx, %ecx
movslq %ecx, %rcx
movl 0x1018(%rax,%rcx,4), %edx
xorl $0x1, %edx
movl %edx, 0x1018(%rax,%rcx,4)
jmp 0x32b8
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0x322c
jmp 0x32c8
movl -0x10(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x10(%rbp)
jmp 0x31f9
movq -0x30(%rbp), %rax
movb $0x1, 0x304c(%rax)
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x37fd
movq -0x30(%rbp), %rax
movzwl (%rax), %eax
andl $0xf, %eax
movl %eax, -0x44(%rbp)
subl $0x1, %eax
je 0x336f
jmp 0x330b
movl -0x44(%rbp), %eax
subl $0xe, %eax
jne 0x33c5
jmp 0x3319
movq -0x30(%rbp), %rax
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1002(%rax,%rcx), %ecx
movzbl 0x303c(%rax,%rcx), %eax
cmpl $0x0, %eax
je 0x3358
movq -0x30(%rbp), %rax
movzwl 0x1014(%rax), %ecx
addl $0x4, %ecx
movw %cx, 0x1014(%rax)
jmp 0x336d
movq -0x30(%rbp), %rax
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x33c5
movq -0x30(%rbp), %rax
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1002(%rax,%rcx), %ecx
movzbl 0x303c(%rax,%rcx), %eax
cmpl $0x0, %eax
jne 0x33ae
movq -0x30(%rbp), %rax
movzwl 0x1014(%rax), %ecx
addl $0x4, %ecx
movw %cx, 0x1014(%rax)
jmp 0x33c3
movq -0x30(%rbp), %rax
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x33c5
jmp 0x37fd
movq -0x30(%rbp), %rax
movzbl (%rax), %eax
movl %eax, -0x48(%rbp)
subl $0x7, %eax
je 0x344e
jmp 0x33db
movl -0x48(%rbp), %eax
subl $0xa, %eax
je 0x3484
jmp 0x33e9
movl -0x48(%rbp), %eax
subl $0x15, %eax
je 0x350c
jmp 0x33f7
movl -0x48(%rbp), %eax
subl $0x18, %eax
je 0x3542
jmp 0x3405
movl -0x48(%rbp), %eax
subl $0x1e, %eax
je 0x3578
jmp 0x3413
movl -0x48(%rbp), %eax
subl $0x29, %eax
je 0x35fc
jmp 0x3421
movl -0x48(%rbp), %eax
subl $0x33, %eax
je 0x3637
jmp 0x342f
movl -0x48(%rbp), %eax
subl $0x55, %eax
je 0x36fd
jmp 0x343d
movl -0x48(%rbp), %eax
subl $0x65, %eax
je 0x377c
jmp 0x37f9
movq -0x30(%rbp), %rax
movb 0x3018(%rax), %dl
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movb %dl, 0x1002(%rax,%rcx)
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x37f9
movb $0x0, 0x5e22(%rip)      # 0x92ad
movb 0x5e1c(%rip), %al       # 0x92ad
xorb $-0x1, %al
testb $0x1, %al
jne 0x3499
jmp 0x34f2
movl $0x0, -0x18(%rbp)
cmpl $0x10, -0x18(%rbp)
jge 0x34f0
movq -0x30(%rbp), %rax
movslq -0x18(%rbp), %rcx
movzbl 0x303c(%rax,%rcx), %eax
cmpl $0x0, %eax
je 0x34e3
movq -0x30(%rbp), %rax
movl -0x18(%rbp), %ecx
movb %cl, %dl
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movb %dl, 0x1002(%rax,%rcx)
movb $0x1, 0x5dcc(%rip)      # 0x92ad
jmp 0x34f0
jmp 0x34e5
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0x34a0
jmp 0x348b
movq -0x30(%rbp), %rax
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x37f9
movq -0x30(%rbp), %rax
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movb 0x1002(%rax,%rcx), %cl
movb %cl, 0x3018(%rax)
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x37f9
movq -0x30(%rbp), %rax
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movb 0x1002(%rax,%rcx), %cl
movb %cl, 0x3019(%rax)
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x37f9
movq -0x30(%rbp), %rcx
movzwl 0x1012(%rcx), %eax
movzwl (%rcx), %edx
andl $0xf00, %edx            # imm = 0xF00
sarl $0x8, %edx
movslq %edx, %rdx
movzbl 0x1002(%rcx,%rdx), %ecx
addl %ecx, %eax
cmpl $0xffff, %eax           # imm = 0xFFFF
jle 0x35b0
movq -0x30(%rbp), %rax
movb $0x1, 0x1011(%rax)
jmp 0x35bb
movq -0x30(%rbp), %rax
movb $0x0, 0x1011(%rax)
movq -0x30(%rbp), %rax
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1002(%rax,%rcx), %edx
movzwl 0x1012(%rax), %ecx
addl %edx, %ecx
movw %cx, 0x1012(%rax)
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x37f9
movq -0x30(%rbp), %rax
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1002(%rax,%rcx), %ecx
imull $0x5, %ecx, %ecx
movw %cx, 0x1012(%rax)
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x37f9
movq -0x30(%rbp), %rax
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1002(%rax,%rcx), %eax
movl $0x64, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movq -0x30(%rbp), %rax
movb %cl, %dl
movzwl 0x1012(%rax), %ecx
movb %dl, 0x2(%rax,%rcx)
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1002(%rax,%rcx), %eax
movl $0xa, %ecx
cltd
idivl %ecx
movl $0xa, %ecx
cltd
idivl %ecx
movq -0x30(%rbp), %rax
movzwl 0x1012(%rax), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movb %dl, 0x2(%rax,%rcx)
movzwl (%rax), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1002(%rax,%rcx), %eax
movl $0x64, %ecx
cltd
idivl %ecx
movl %edx, %eax
movl $0xa, %ecx
cltd
idivl %ecx
movq -0x30(%rbp), %rax
movzwl 0x1012(%rax), %ecx
addl $0x2, %ecx
movslq %ecx, %rcx
movb %dl, 0x2(%rax,%rcx)
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x37f9
movl $0x0, -0x1c(%rbp)
movq -0x30(%rbp), %rcx
movl -0x1c(%rbp), %eax
movzwl (%rcx), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
cmpl %ecx, %eax
jg 0x3746
movq -0x30(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movb 0x1002(%rax,%rcx), %dl
movzwl 0x1012(%rax), %ecx
addl -0x1c(%rbp), %ecx
movslq %ecx, %rcx
movb %dl, 0x2(%rax,%rcx)
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x3704
movq -0x30(%rbp), %rax
movzwl (%rax), %edx
andl $0xf00, %edx            # imm = 0xF00
sarl $0x8, %edx
addl $0x1, %edx
movzwl 0x1012(%rax), %ecx
addl %edx, %ecx
movw %cx, 0x1012(%rax)
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x37f9
movl $0x0, -0x20(%rbp)
movq -0x30(%rbp), %rcx
movl -0x20(%rbp), %eax
movzwl (%rcx), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
cmpl %ecx, %eax
jg 0x37c5
movq -0x30(%rbp), %rax
movzwl 0x1012(%rax), %ecx
addl -0x20(%rbp), %ecx
movslq %ecx, %rcx
movb 0x2(%rax,%rcx), %dl
movslq -0x20(%rbp), %rcx
movb %dl, 0x1002(%rax,%rcx)
movl -0x20(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x20(%rbp)
jmp 0x3783
movq -0x30(%rbp), %rax
movzwl (%rax), %edx
andl $0xf00, %edx            # imm = 0xF00
sarl $0x8, %edx
addl $0x1, %edx
movzwl 0x1012(%rax), %ecx
addl %edx, %ecx
movw %cx, 0x1012(%rax)
movzwl 0x1014(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1014(%rax)
jmp 0x37fd
jmp 0x37fd
movq -0x30(%rbp), %rax
movzbl 0x3018(%rax), %eax
cmpl $0x0, %eax
jle 0x3820
movq -0x30(%rbp), %rax
movb 0x3018(%rax), %cl
addb $-0x1, %cl
movb %cl, 0x3018(%rax)
movq -0x30(%rbp), %rax
movzbl 0x3019(%rax), %eax
cmpl $0x0, %eax
jle 0x384d
movq -0x30(%rbp), %rax
movzbl 0x3019(%rax), %eax
cmpl $0x1, %eax
jne 0x384b
movq -0x30(%rbp), %rax
movb $0x1, 0x304d(%rax)
jmp 0x384d
movq -0x30(%rbp), %rax
movb 0x3019(%rax), %cl
addb $-0x1, %cl
movb %cl, 0x3019(%rax)
addq $0x50, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)