// File: thanoskoutr[P]Chip-8-Emulator/chip8.cpp
// Function: Chip8::emulateCycle()
void Chip8::emulateCycle()
{
  /* Fetch next Opcode from memory */
  unsigned short opcode = memory[pc] << 8 | memory[pc + 1];  // opcode is 2 bytes, memory stores 1 byte

  /* Decode Opcode */
  switch (opcode & 0xF000)  // Switch on MSB
  {
    case 0x0000:
      switch (opcode & 0x000F)
      {
        case 0x0000:  // 00E0 - CLS: Clear the display.
          for (int i = 0; i < SCREEN_SIZE; i++)
            gfx[i] = 0x0;
          drawFlag = true;
          pc += 2;
        break;

        case 0x000E:  // 00EE - RET: Return from a subroutine.
          sp--;
          pc = stack[sp];
          pc += 2;
        break;

        default:
          printf ("Unknown opcode [0x0000]: 0x%X\n", opcode);
      }
    break;

    case 0x1000:  // 1nnn - JP addr: Jump to location nnn.
      pc = opcode & 0x0FFF;
    break;

    case 0x2000:  // 2nnn - CALL addr: Call subroutine at nnn.
      stack[sp] = pc;
      sp++;
      pc = opcode & 0x0FFF;
    break;

    case 0x3000:  // 3xkk - SE Vx, byte: Skip next instruction if Vx = kk.
      if (V[(opcode & 0x0F00) >> 8] == (opcode & 0x00FF))
        pc += 4;
      else
        pc += 2;
    break;

    case 0x4000:  // 4xkk - SNE Vx, byte: Skip next instruction if Vx != kk.
      if (V[(opcode & 0x0F00) >> 8] != (opcode & 0x00FF))
        pc += 4;
      else
        pc += 2;
    break;

    case 0x5000:  // 5xy0 - SE Vx, Vy: Skip next instruction if Vx = Vy.
      if (V[(opcode & 0x0F00) >> 8] == V[(opcode & 0x00F0) >> 4])
        pc += 4;
      else
        pc += 2;
    break;

    case 0x6000:  // 6xkk - LD Vx, byte: Set Vx = kk.
      V[(opcode & 0x0F00) >> 8] = opcode & 0x00FF;
      pc += 2;
    break;

    case 0x7000:  // 7xkk - ADD Vx, byte: Set Vx = Vx + kk.
      V[(opcode & 0x0F00) >> 8] += opcode & 0x00FF;
      pc += 2;
    break;

    case 0x8000:
      switch (opcode & 0x000F)
      {
        case 0x0000:  // 8xy0 - LD Vx, Vy: Set Vx = Vy.
          V[(opcode & 0x0F00) >> 8] = V[(opcode & 0x00F0) >> 4];
          pc += 2;
        break;

        case 0x0001:  // 8xy1 - OR Vx, Vy: Set Vx = Vx OR Vy.
          V[(opcode & 0x0F00) >> 8] |= V[(opcode & 0x00F0) >> 4];
          pc += 2;
        break;

        case 0x0002:  // 8xy2 - AND Vx, Vy: Set Vx = Vx AND Vy.
          V[(opcode & 0x0F00) >> 8] &= V[(opcode & 0x00F0) >> 4];
          pc += 2;
        break;

        case 0x0003:  // 8xy3 - XOR Vx, Vy: Set Vx = Vx XOR Vy.
          V[(opcode & 0x0F00) >> 8] ^= V[(opcode & 0x00F0) >> 4];
          pc += 2;
        break;

        case 0x0004:  //  8xy4 - ADD Vx, Vy: Set Vx = Vx + Vy, set VF = carry.
          if (V[(opcode & 0x0F00) >> 8] + V[(opcode & 0x00F0) >> 4] > 0xFF) // Check for overflow
            V[0xF] = 1;
          else
            V[0xF] = 0;
          V[(opcode & 0x0F00) >> 8] += V[(opcode & 0x00F0) >> 4];
          pc += 2;
        break;

        case 0x0005:  //  8xy5 - SUB Vx, Vy: Set Vx = Vx - Vy, set VF = NOT borrow.
          if (V[(opcode & 0x0F00) >> 8] > V[(opcode & 0x00F0) >> 4])  // check Vx-Vy
            V[0xF] = 1;
          else
            V[0xF] = 0;
          V[(opcode & 0x0F00) >> 8] -= V[(opcode & 0x00F0) >> 4];
          pc += 2;
        break;

        case 0x0006:  //  8xy6 - SHR Vx {, Vy}: Set Vx = Vx SHR 1.
          if ((V[(opcode & 0x0F00) >> 8] & 0x1) == 1) // Check if LSB == 1
            V[0xF] = 1;
          else
            V[0xF] = 0;
          V[(opcode & 0x0F00) >> 8] >>= 1;  // divide by 2 == bitwise right shift with 1
          pc += 2;
        break;

        case 0x0007:  // 8xy7 - SUBN Vx, Vy: Set Vx = Vy - Vx, set VF = NOT borrow.
          if (V[(opcode & 0x0F00) >> 8] < V[(opcode & 0x00F0) >> 4])  // check Vy-Vx
            V[0xF] = 1;
          else
            V[0xF] = 0;
          V[(opcode & 0x0F00) >> 8] = V[(opcode & 0x00F0) >> 4] - V[(opcode & 0x0F00) >> 8];
          pc += 2;
        break;

        case 0x000E:  // 8xyE - SHL Vx {, Vy}: Set Vx = Vx SHL 1.
          if (V[(opcode & 0x0F00) >> 8] >> 7 == 1) // Check if MSB == 1
            V[0xF] = 1;
          else
            V[0xF] = 0;
          V[(opcode & 0x0F00) >> 8] <<= 1;  // multiply by 2 == bitwise left shift with 1
          pc += 2;
        break;

        default:
          printf ("Unknown opcode [0x8000]: 0x%X\n", opcode);
      }
    break;

    case 0x9000:  // 9xy0 - SNE Vx, Vy: Skip next instruction if Vx != Vy.
      if (V[(opcode & 0x0F00) >> 8] != V[(opcode & 0x00F0) >> 4])
        pc += 4;
      else
        pc += 2;
    break;

    case 0xA000:  // Annn - LD I, addr: Set I = nnn.
      I = opcode & 0x0FFF;
      pc += 2;
    break;

    case 0xB000:  // Bnnn - JP V0, addr: Jump to location nnn + V0.
      pc = (opcode & 0x0FFF) + V[0];
    break;

    case 0xC000:  // Cxkk - RND Vx, byte: Set Vx = random byte AND kk.
      V[(opcode & 0x0F00) >> 8] = (rand() % 0xFF) & (opcode & 0x00FF);  // generate random number between 0-255
      pc += 2;
    break;

    case 0xD000:  // Dxyn - DRW Vx, Vy, nibble: Display n-byte sprite starting at memory location I at (Vx, Vy), set VF = collision.
    {
      /* A sprite is a set of 8 pixels = 8 bits = 1 byte,
       * Each row of 8 pixels is read as bit-coded starting from memory location I;
       * I value doesn't change after the execution of this instruction.
       * VF is set to 1 if any screen pixels are flipped from set to unset when the sprite is drawn,
         and to 0 if that doesn't happen */

      unsigned short x = V[(opcode & 0x0F00) >> 8];
      unsigned short y = V[(opcode & 0x00F0) >> 4];
      unsigned short height = opcode & 0x000F;
      unsigned short sprite;

      V[0xF] = 0;
      for (int yLine = 0; yLine < height; yLine++)  // read for n-byte sprites
      {
        sprite = memory[I + yLine];  // sprite represents 1 hex value e.g. 0xF2 (= 1 byte = 8 bits = 8 pixels)
        for (int xLine = 0; xLine < 8; xLine++) // each row is 8 pixels
        {
          if ((sprite & (0x80 >> xLine)) != 0 ) // For each bit of the sprite that is 1, 0x80 = 1000 0000
          {
            if (gfx[((y + yLine) * SCREEN_WIDTH) + (x + xLine)] == 1) // Check if the pixel on the display is set to 1
              V[0xF] = 1;
            gfx[((y + yLine) * SCREEN_WIDTH) + (x + xLine)] ^= 1; // Set the pixel value by using XOR
          }
        }
      }
      drawFlag = true;
      pc += 2;
    }
    break;

    case 0xE000:
      switch (opcode & 0x00FF)
      {
        case 0x009E:  // Ex9E - SKP Vx: Skip next instruction if key with the value of Vx is pressed.
          if (key[V[(opcode & 0x0F00) >> 8]] != 0)
            pc += 4;
          else
            pc += 2;
        break;

        case 0x00A1:  // ExA1 - SKNP Vx: Skip next instruction if key with the value of Vx is not pressed.
          if (key[V[(opcode & 0x0F00) >> 8]] == 0)
            pc += 4;
          else
            pc += 2;
        break;

        default:
          printf ("Unknown opcode [0xE000]: 0x%X\n", opcode);
      }
    break;

    case 0xF000:
      switch (opcode & 0x00FF)
      {
        case 0x0007:  // Fx07 - LD Vx, DT: Set Vx = delay timer value.
          V[(opcode & 0x0F00) >> 8] = delay_timer;
          pc += 2;
        break;

        case 0x000A:  // Fx0A - LD Vx, K: Wait for a key press, store the value of the key in Vx.
        {
          bool isPressed = false;
          for (int i = 0; i < KEY_SIZE; i++)
          {
            if (key[i] != 0)
            {
              V[(opcode & 0x0F00) >> 8] = key[i]; // or Vx = i
              isPressed = true;
            }
          }
          if (!isPressed) // If no key pressed, skip this cycle and try again
            return;
          pc += 2;
        }
        break;

        case 0x0015:  // Fx15 - LD DT, Vx: Set delay timer = Vx.
          delay_timer = V[(opcode & 0x0F00) >> 8];
          pc += 2;
        break;

        case 0x0018:  // Fx18 - LD ST, Vx: ST is set equal to the value of Vx.
          sound_timer = V[(opcode & 0x0F00) >> 8];
          pc += 2;
        break;

        case 0x001E:  // Fx1E - ADD I, Vx: Set I = I + Vx.
          if (I + V[(opcode & 0x0F00) >> 8] > 0xFFF) // Check for overflow, undocumented feature
            V[0xF] = 1;
          else
            V[0xF] = 0;
          I += V[(opcode & 0x0F00) >> 8];
          pc += 2;
        break;

        case 0x0029:  // Fx29 - LD F, Vx: Set I = location of sprite for digit Vx.
          I = V[(opcode & 0x0F00) >> 8] * 0x5;  // Each character in font takes 5 bytes of memory
          pc += 2;
        break;

        case 0x0033:  // Fx33 - LD B, Vx: Store BCD representation of Vx in memory locations I, I+1, and I+2.
          memory[I]   = (V[(opcode & 0x0F00) >> 8] / 100);       // hundreds
          memory[I+1] = (V[(opcode & 0x0F00) >> 8] / 10) % 10;   // tens
          memory[I+2] = (V[(opcode & 0x0F00) >> 8]) % 10;        // ones
          pc += 2;
        break;

        case 0x0055:  // Fx55 - LD [I], Vx: Store registers V0 through Vx in memory starting at location I.
          for (int i = 0; i <= ((opcode & 0x0F00) >> 8); i++)
            memory[I + i] = V[i];
          /* On the original interpreter, when the operation is done, I = I + X + 1 (I is incremented).
             In SCHIP, I is left unmodified. */
					I += ((opcode & 0x0F00) >> 8) + 1;
          pc += 2;
        break;

        case 0x0065:  // Fx65 - LD Vx, [I]: Read registers V0 through Vx from memory starting at location I.
          for (int i = 0; i <= ((opcode & 0x0F00) >> 8); i++)
            V[i] = memory[I + i];
          /* On the original interpreter, when the operation is done, I = I + X + 1 (I is incremented).
             In SCHIP, I is left unmodified. */
					I += ((opcode & 0x0F00) >> 8) + 1;
          pc += 2;
        break;

        default:
          printf ("Unknown opcode [0xF000]: 0x%X\n", opcode);
      }
    break;

    default:
      printf ("Unknown opcode: 0x%X\n", opcode);
  }

  /* Update Timers */
  if (delay_timer > 0)
    delay_timer--;

  if (sound_timer > 0)
  {
    if (sound_timer == 1)
      sound_timer--;
  }

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rcx
movq %rcx, -0x40(%rbp)
movzwl 0x1826(%rcx), %eax
movl %eax, %edx
movzbl 0x814(%rcx,%rdx), %eax
shll $0x8, %eax
movzbl 0x815(%rcx,%rdx), %ecx
orl %ecx, %eax
movw %ax, -0xa(%rbp)
movzwl -0xa(%rbp), %eax
andl $0xf000, %eax           # imm = 0xF000
movl %eax, -0x34(%rbp)
je 0x29fd
jmp 0x290a
movl -0x34(%rbp), %eax
subl $0x1000, %eax           # imm = 0x1000
je 0x2ab0
jmp 0x291a
movl -0x34(%rbp), %eax
subl $0x2000, %eax           # imm = 0x2000
je 0x2aca
jmp 0x292a
movl -0x34(%rbp), %eax
subl $0x3000, %eax           # imm = 0x3000
je 0x2b0c
jmp 0x293a
movl -0x34(%rbp), %eax
subl $0x4000, %eax           # imm = 0x4000
je 0x2b67
jmp 0x294a
movl -0x34(%rbp), %eax
subl $0x5000, %eax           # imm = 0x5000
je 0x2bc2
jmp 0x295a
movl -0x34(%rbp), %eax
subl $0x6000, %eax           # imm = 0x6000
je 0x2c29
jmp 0x296a
movl -0x34(%rbp), %eax
subl $0x7000, %eax           # imm = 0x7000
je 0x2c66
jmp 0x297a
movl -0x34(%rbp), %eax
subl $0x8000, %eax           # imm = 0x8000
je 0x2cab
jmp 0x298a
movl -0x34(%rbp), %eax
subl $0x9000, %eax           # imm = 0x9000
je 0x3112
jmp 0x299a
movl -0x34(%rbp), %eax
subl $0xa000, %eax           # imm = 0xA000
je 0x3179
jmp 0x29aa
movl -0x34(%rbp), %eax
subl $0xb000, %eax           # imm = 0xB000
je 0x31a4
jmp 0x29ba
movl -0x34(%rbp), %eax
subl $0xc000, %eax           # imm = 0xC000
je 0x31c7
jmp 0x29ca
movl -0x34(%rbp), %eax
subl $0xd000, %eax           # imm = 0xD000
je 0x3211
jmp 0x29da
movl -0x34(%rbp), %eax
subl $0xe000, %eax           # imm = 0xE000
je 0x3345
jmp 0x29ea
movl -0x34(%rbp), %eax
subl $0xf000, %eax           # imm = 0xF000
je 0x3429
jmp 0x3872
movzwl -0xa(%rbp), %eax
andl $0xf, %eax
movl %eax, -0x44(%rbp)
je 0x2a18
jmp 0x2a0b
movl -0x44(%rbp), %eax
subl $0xe, %eax
je 0x2a5a
jmp 0x2a99
movl $0x0, -0x10(%rbp)
cmpl $0x800, -0x10(%rbp)     # imm = 0x800
jge 0x2a40
movq -0x40(%rbp), %rax
movslq -0x10(%rbp), %rcx
movb $0x0, 0x1(%rax,%rcx)
movl -0x10(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x10(%rbp)
jmp 0x2a1f
movq -0x40(%rbp), %rax
movb $0x1, (%rax)
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x2aab
movq -0x40(%rbp), %rax
movw 0x1848(%rax), %cx
addw $-0x1, %cx
movw %cx, 0x1848(%rax)
movzwl 0x1848(%rax), %ecx
movw 0x1828(%rax,%rcx,2), %cx
movw %cx, 0x1826(%rax)
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x2aab
movzwl -0xa(%rbp), %esi
leaq 0x4663(%rip), %rdi      # 0x7107
movb $0x0, %al
callq 0x2060
jmp 0x3884
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %ecx
andl $0xfff, %ecx            # imm = 0xFFF
movw %cx, 0x1826(%rax)
jmp 0x3884
movq -0x40(%rbp), %rax
movw 0x1826(%rax), %dx
movzwl 0x1848(%rax), %ecx
movw %dx, 0x1828(%rax,%rcx,2)
movw 0x1848(%rax), %cx
addw $0x1, %cx
movw %cx, 0x1848(%rax)
movzwl -0xa(%rbp), %ecx
andl $0xfff, %ecx            # imm = 0xFFF
movw %cx, 0x1826(%rax)
jmp 0x3884
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %eax
movzwl -0xa(%rbp), %ecx
andl $0xff, %ecx
cmpl %ecx, %eax
jne 0x2b4d
movq -0x40(%rbp), %rax
movzwl 0x1826(%rax), %ecx
addl $0x4, %ecx
movw %cx, 0x1826(%rax)
jmp 0x2b62
movq -0x40(%rbp), %rax
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x3884
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %eax
movzwl -0xa(%rbp), %ecx
andl $0xff, %ecx
cmpl %ecx, %eax
je 0x2ba8
movq -0x40(%rbp), %rax
movzwl 0x1826(%rax), %ecx
addl $0x4, %ecx
movw %cx, 0x1826(%rax)
jmp 0x2bbd
movq -0x40(%rbp), %rax
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x3884
movq -0x40(%rbp), %rcx
movzwl -0xa(%rbp), %eax
andl $0xf00, %eax            # imm = 0xF00
sarl $0x8, %eax
cltq
movzbl 0x1814(%rcx,%rax), %eax
movzwl -0xa(%rbp), %edx
andl $0xf0, %edx
sarl $0x4, %edx
movslq %edx, %rdx
movzbl 0x1814(%rcx,%rdx), %ecx
cmpl %ecx, %eax
jne 0x2c0f
movq -0x40(%rbp), %rax
movzwl 0x1826(%rax), %ecx
addl $0x4, %ecx
movw %cx, 0x1826(%rax)
jmp 0x2c24
movq -0x40(%rbp), %rax
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x3884
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %ecx
andl $0xff, %ecx
movb %cl, %dl
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movb %dl, 0x1814(%rax,%rcx)
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x3884
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %esi
andl $0xff, %esi
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %edx
addl %esi, %edx
movb %dl, 0x1814(%rax,%rcx)
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x3884
movzwl -0xa(%rbp), %eax
andl $0xf, %eax
movl %eax, %ecx
movq %rcx, -0x50(%rbp)
subl $0xe, %eax
ja 0x30fb
movq -0x50(%rbp), %rax
leaq 0x4338(%rip), %rcx      # 0x7004
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %ecx
andl $0xf0, %ecx
sarl $0x4, %ecx
movslq %ecx, %rcx
movb 0x1814(%rax,%rcx), %dl
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movb %dl, 0x1814(%rax,%rcx)
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x310d
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %ecx
andl $0xf0, %ecx
sarl $0x4, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %esi
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %edx
orl %esi, %edx
movb %dl, 0x1814(%rax,%rcx)
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x310d
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %ecx
andl $0xf0, %ecx
sarl $0x4, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %esi
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %edx
andl %esi, %edx
movb %dl, 0x1814(%rax,%rcx)
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x310d
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %ecx
andl $0xf0, %ecx
sarl $0x4, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %esi
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %edx
xorl %esi, %edx
movb %dl, 0x1814(%rax,%rcx)
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x310d
movq -0x40(%rbp), %rcx
movzwl -0xa(%rbp), %eax
andl $0xf00, %eax            # imm = 0xF00
sarl $0x8, %eax
cltq
movzbl 0x1814(%rcx,%rax), %eax
movzwl -0xa(%rbp), %edx
andl $0xf0, %edx
sarl $0x4, %edx
movslq %edx, %rdx
movzbl 0x1814(%rcx,%rdx), %ecx
addl %ecx, %eax
cmpl $0xff, %eax
jle 0x2e5e
movq -0x40(%rbp), %rax
movb $0x1, 0x1823(%rax)
jmp 0x2e69
movq -0x40(%rbp), %rax
movb $0x0, 0x1823(%rax)
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %ecx
andl $0xf0, %ecx
sarl $0x4, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %esi
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %edx
addl %esi, %edx
movb %dl, 0x1814(%rax,%rcx)
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x310d
movq -0x40(%rbp), %rcx
movzwl -0xa(%rbp), %eax
andl $0xf00, %eax            # imm = 0xF00
sarl $0x8, %eax
cltq
movzbl 0x1814(%rcx,%rax), %eax
movzwl -0xa(%rbp), %edx
andl $0xf0, %edx
sarl $0x4, %edx
movslq %edx, %rdx
movzbl 0x1814(%rcx,%rdx), %ecx
cmpl %ecx, %eax
jle 0x2eff
movq -0x40(%rbp), %rax
movb $0x1, 0x1823(%rax)
jmp 0x2f0a
movq -0x40(%rbp), %rax
movb $0x0, 0x1823(%rax)
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %ecx
andl $0xf0, %ecx
sarl $0x4, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %esi
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %edx
subl %esi, %edx
movb %dl, 0x1814(%rax,%rcx)
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x310d
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %eax
andl $0x1, %eax
cmpl $0x1, %eax
jne 0x2f8e
movq -0x40(%rbp), %rax
movb $0x1, 0x1823(%rax)
jmp 0x2f99
movq -0x40(%rbp), %rax
movb $0x0, 0x1823(%rax)
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %edx
sarl %edx
movb %dl, 0x1814(%rax,%rcx)
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x310d
movq -0x40(%rbp), %rcx
movzwl -0xa(%rbp), %eax
andl $0xf00, %eax            # imm = 0xF00
sarl $0x8, %eax
cltq
movzbl 0x1814(%rcx,%rax), %eax
movzwl -0xa(%rbp), %edx
andl $0xf0, %edx
sarl $0x4, %edx
movslq %edx, %rdx
movzbl 0x1814(%rcx,%rdx), %ecx
cmpl %ecx, %eax
jge 0x3017
movq -0x40(%rbp), %rax
movb $0x1, 0x1823(%rax)
jmp 0x3022
movq -0x40(%rbp), %rax
movb $0x0, 0x1823(%rax)
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %ecx
andl $0xf0, %ecx
sarl $0x4, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %ecx
movzwl -0xa(%rbp), %edx
andl $0xf00, %edx            # imm = 0xF00
sarl $0x8, %edx
movslq %edx, %rdx
movzbl 0x1814(%rax,%rdx), %edx
subl %edx, %ecx
movb %cl, %dl
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movb %dl, 0x1814(%rax,%rcx)
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x310d
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %eax
sarl $0x7, %eax
cmpl $0x1, %eax
jne 0x30b8
movq -0x40(%rbp), %rax
movb $0x1, 0x1823(%rax)
jmp 0x30c3
movq -0x40(%rbp), %rax
movb $0x0, 0x1823(%rax)
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %edx
shll %edx
movb %dl, 0x1814(%rax,%rcx)
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x310d
movzwl -0xa(%rbp), %esi
leaq 0x4020(%rip), %rdi      # 0x7126
movb $0x0, %al
callq 0x2060
jmp 0x3884
movq -0x40(%rbp), %rcx
movzwl -0xa(%rbp), %eax
andl $0xf00, %eax            # imm = 0xF00
sarl $0x8, %eax
cltq
movzbl 0x1814(%rcx,%rax), %eax
movzwl -0xa(%rbp), %edx
andl $0xf0, %edx
sarl $0x4, %edx
movslq %edx, %rdx
movzbl 0x1814(%rcx,%rdx), %ecx
cmpl %ecx, %eax
je 0x315f
movq -0x40(%rbp), %rax
movzwl 0x1826(%rax), %ecx
addl $0x4, %ecx
movw %cx, 0x1826(%rax)
jmp 0x3174
movq -0x40(%rbp), %rax
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x3884
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %ecx
andl $0xfff, %ecx            # imm = 0xFFF
movw %cx, 0x1824(%rax)
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x3884
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %ecx
andl $0xfff, %ecx            # imm = 0xFFF
movzbl 0x1814(%rax), %edx
addl %edx, %ecx
movw %cx, 0x1826(%rax)
jmp 0x3884
callq 0x20b0
movl $0xff, %ecx
cltd
idivl %ecx
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %ecx
andl $0xff, %ecx
andl %ecx, %edx
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movb %dl, 0x1814(%rax,%rcx)
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x3884
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %ecx
movw %cx, -0x12(%rbp)
movzwl -0xa(%rbp), %ecx
andl $0xf0, %ecx
sarl $0x4, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %ecx
movw %cx, -0x14(%rbp)
movzwl -0xa(%rbp), %ecx
andl $0xf, %ecx
movw %cx, -0x16(%rbp)
movb $0x0, 0x1823(%rax)
movl $0x0, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
movzwl -0x16(%rbp), %ecx
cmpl %ecx, %eax
jge 0x3328
movq -0x40(%rbp), %rax
movzwl 0x1824(%rax), %ecx
addl -0x1c(%rbp), %ecx
movslq %ecx, %rcx
movzbl 0x814(%rax,%rcx), %eax
movw %ax, -0x18(%rbp)
movl $0x0, -0x20(%rbp)
cmpl $0x8, -0x20(%rbp)
jge 0x3318
movzwl -0x18(%rbp), %eax
movl -0x20(%rbp), %ecx
movl $0x80, %edx
sarl %cl, %edx
movl %edx, %ecx
andl %ecx, %eax
cmpl $0x0, %eax
je 0x330b
movq -0x40(%rbp), %rax
movzwl -0x14(%rbp), %ecx
addl -0x1c(%rbp), %ecx
shll $0x6, %ecx
movzwl -0x12(%rbp), %edx
addl -0x20(%rbp), %edx
addl %edx, %ecx
movslq %ecx, %rcx
movzbl 0x1(%rax,%rcx), %eax
cmpl $0x1, %eax
jne 0x32e5
movq -0x40(%rbp), %rax
movb $0x1, 0x1823(%rax)
movq -0x40(%rbp), %rax
movzwl -0x14(%rbp), %ecx
addl -0x1c(%rbp), %ecx
shll $0x6, %ecx
movzwl -0x12(%rbp), %edx
addl -0x20(%rbp), %edx
addl %edx, %ecx
movslq %ecx, %rcx
movzbl 0x1(%rax,%rcx), %edx
xorl $0x1, %edx
movb %dl, 0x1(%rax,%rcx)
jmp 0x330d
movl -0x20(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x20(%rbp)
jmp 0x3299
jmp 0x331a
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x3266
movq -0x40(%rbp), %rax
movb $0x1, (%rax)
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x3884
movzbl -0xa(%rbp), %eax
movl %eax, -0x54(%rbp)
subl $0x9e, %eax
je 0x3364
jmp 0x3355
movl -0x54(%rbp), %eax
subl $0xa1, %eax
je 0x33bb
jmp 0x3412
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %ecx
movzbl 0x801(%rax,%rcx), %eax
cmpl $0x0, %eax
je 0x33a4
movq -0x40(%rbp), %rax
movzwl 0x1826(%rax), %ecx
addl $0x4, %ecx
movw %cx, 0x1826(%rax)
jmp 0x33b9
movq -0x40(%rbp), %rax
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x3424
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %ecx
movzbl 0x801(%rax,%rcx), %eax
cmpl $0x0, %eax
jne 0x33fb
movq -0x40(%rbp), %rax
movzwl 0x1826(%rax), %ecx
addl $0x4, %ecx
movw %cx, 0x1826(%rax)
jmp 0x3410
movq -0x40(%rbp), %rax
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x3424
movzwl -0xa(%rbp), %esi
leaq 0x3d28(%rip), %rdi      # 0x7145
movb $0x0, %al
callq 0x2060
jmp 0x3884
movzbl -0xa(%rbp), %eax
movl %eax, -0x58(%rbp)
subl $0x7, %eax
je 0x34aa
jmp 0x3437
movl -0x58(%rbp), %eax
subl $0xa, %eax
je 0x34e1
jmp 0x3445
movl -0x58(%rbp), %eax
subl $0x15, %eax
je 0x3563
jmp 0x3453
movl -0x58(%rbp), %eax
subl $0x18, %eax
je 0x359a
jmp 0x3461
movl -0x58(%rbp), %eax
subl $0x1e, %eax
je 0x35d1
jmp 0x346f
movl -0x58(%rbp), %eax
subl $0x29, %eax
je 0x3657
jmp 0x347d
movl -0x58(%rbp), %eax
subl $0x33, %eax
je 0x3693
jmp 0x348b
movl -0x58(%rbp), %eax
subl $0x55, %eax
je 0x375b
jmp 0x3499
movl -0x58(%rbp), %eax
subl $0x65, %eax
je 0x37de
jmp 0x385e
movq -0x40(%rbp), %rax
movb 0x184a(%rax), %dl
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movb %dl, 0x1814(%rax,%rcx)
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x3870
movb $0x0, -0x21(%rbp)
movl $0x0, -0x28(%rbp)
cmpl $0x10, -0x28(%rbp)
jge 0x353e
movq -0x40(%rbp), %rax
movslq -0x28(%rbp), %rcx
movzbl 0x801(%rax,%rcx), %eax
cmpl $0x0, %eax
je 0x3531
movq -0x40(%rbp), %rax
movslq -0x28(%rbp), %rcx
movb 0x801(%rax,%rcx), %dl
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movb %dl, 0x1814(%rax,%rcx)
movb $0x1, -0x21(%rbp)
jmp 0x3533
movl -0x28(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x28(%rbp)
jmp 0x34ec
testb $0x1, -0x21(%rbp)
jne 0x3549
jmp 0x38dc
movq -0x40(%rbp), %rax
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x3870
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movb 0x1814(%rax,%rcx), %cl
movb %cl, 0x184a(%rax)
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x3870
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movb 0x1814(%rax,%rcx), %cl
movb %cl, 0x184b(%rax)
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x3870
movq -0x40(%rbp), %rcx
movzwl 0x1824(%rcx), %eax
movzwl -0xa(%rbp), %edx
andl $0xf00, %edx            # imm = 0xF00
sarl $0x8, %edx
movslq %edx, %rdx
movzbl 0x1814(%rcx,%rdx), %ecx
addl %ecx, %eax
cmpl $0xfff, %eax            # imm = 0xFFF
jle 0x360a
movq -0x40(%rbp), %rax
movb $0x1, 0x1823(%rax)
jmp 0x3615
movq -0x40(%rbp), %rax
movb $0x0, 0x1823(%rax)
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %edx
movzwl 0x1824(%rax), %ecx
addl %edx, %ecx
movw %cx, 0x1824(%rax)
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x3870
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %ecx
imull $0x5, %ecx, %ecx
movw %cx, 0x1824(%rax)
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x3870
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %eax
movl $0x64, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movq -0x40(%rbp), %rax
movb %cl, %dl
movzwl 0x1824(%rax), %ecx
movb %dl, 0x814(%rax,%rcx)
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %eax
movl $0xa, %ecx
cltd
idivl %ecx
movl $0xa, %ecx
cltd
idivl %ecx
movq -0x40(%rbp), %rax
movzwl 0x1824(%rax), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movb %dl, 0x814(%rax,%rcx)
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
movslq %ecx, %rcx
movzbl 0x1814(%rax,%rcx), %eax
movl $0xa, %ecx
cltd
idivl %ecx
movq -0x40(%rbp), %rax
movzwl 0x1824(%rax), %ecx
addl $0x2, %ecx
movslq %ecx, %rcx
movb %dl, 0x814(%rax,%rcx)
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x3870
movl $0x0, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
cmpl %ecx, %eax
jg 0x37a4
movq -0x40(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movb 0x1814(%rax,%rcx), %dl
movzwl 0x1824(%rax), %ecx
addl -0x2c(%rbp), %ecx
movslq %ecx, %rcx
movb %dl, 0x814(%rax,%rcx)
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x3762
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %edx
andl $0xf00, %edx            # imm = 0xF00
sarl $0x8, %edx
addl $0x1, %edx
movzwl 0x1824(%rax), %ecx
addl %edx, %ecx
movw %cx, 0x1824(%rax)
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x3870
movl $0x0, -0x30(%rbp)
movl -0x30(%rbp), %eax
movzwl -0xa(%rbp), %ecx
andl $0xf00, %ecx            # imm = 0xF00
sarl $0x8, %ecx
cmpl %ecx, %eax
jg 0x3827
movq -0x40(%rbp), %rax
movzwl 0x1824(%rax), %ecx
addl -0x30(%rbp), %ecx
movslq %ecx, %rcx
movb 0x814(%rax,%rcx), %dl
movslq -0x30(%rbp), %rcx
movb %dl, 0x1814(%rax,%rcx)
movl -0x30(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x30(%rbp)
jmp 0x37e5
movq -0x40(%rbp), %rax
movzwl -0xa(%rbp), %edx
andl $0xf00, %edx            # imm = 0xF00
sarl $0x8, %edx
addl $0x1, %edx
movzwl 0x1824(%rax), %ecx
addl %edx, %ecx
movw %cx, 0x1824(%rax)
movzwl 0x1826(%rax), %ecx
addl $0x2, %ecx
movw %cx, 0x1826(%rax)
jmp 0x3870
movzwl -0xa(%rbp), %esi
leaq 0x38fb(%rip), %rdi      # 0x7164
movb $0x0, %al
callq 0x2060
jmp 0x3884
movzwl -0xa(%rbp), %esi
leaq 0x3906(%rip), %rdi      # 0x7183
movb $0x0, %al
callq 0x2060
movq -0x40(%rbp), %rax
movzbl 0x184a(%rax), %eax
cmpl $0x0, %eax
jle 0x38a7
movq -0x40(%rbp), %rax
movb 0x184a(%rax), %cl
addb $-0x1, %cl
movb %cl, 0x184a(%rax)
movq -0x40(%rbp), %rax
movzbl 0x184b(%rax), %eax
cmpl $0x0, %eax
jle 0x38dc
movq -0x40(%rbp), %rax
movzbl 0x184b(%rax), %eax
cmpl $0x1, %eax
jne 0x38da
movq -0x40(%rbp), %rax
movb 0x184b(%rax), %cl
addb $-0x1, %cl
movb %cl, 0x184b(%rax)
jmp 0x38dc
addq $0x60, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
nopl (%rax)