// File: jBlinden[P]private-codis/ProtocolServer.cpp
// Function: RunServerProtocol(CSocket*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>)
void RunServerProtocol(CSocket *socket, string pArgsFile, string serverDataDir)
{
  ServerLog("starting server protocol");
#if !OPTIMAL
  ServerLog("Reading in protocol args");
#endif

  ifstream in;
  in.open(pArgsFile, ios::in | ios::binary);
  struct ProtocolArgs pArgs(in);
  in.close();

#if !OPTIMAL
  ServerLog("Reading in sender OTs");
#endif

  ifstream sOTFile1;
  sOTFile1.open(serverDataDir + "sOT.txt", ios::in | ios::binary);

  SenderOTCorrelation **FSM1_SC = ReadInSenderOTsFSM1(sOTFile1, pArgs);
  SenderOTCorrelation **FSM2_SC = ReadInSenderOTsFSM2(sOTFile1, pArgs);

  sOTFile1.close();

#if !OPTIMAL
  ServerLog("Finished Reading in OTs");
  ServerLog("Creating fake DB");
#endif

  uint32_t N = pArgs.N;
  uint32_t C = pArgs.C;
  uint8_t* bits_per_component = pArgs.bits_per_component;

  ifstream dbFile;
  dbFile.open(serverDataDir + "db.txt");
  uint32_t **db = ReadInDB(dbFile, N, C);
  dbFile.close();

#if VERBOSE
  for (int i = 0; i < N; i++)
  {
    for (int j = 0; j < C; j++)
    {
      cout << db[i][j] << ", ";
    }
    cout << endl;
  }
#endif

#if !OPTIMAL
  ServerLog("Creating random permutations");
#endif

  AESContext PRF;

  uint16_t **flipped_bits = new uint16_t *[N];
  for (int i = 0; i < N; i++)
  {
    flipped_bits[i] = new uint16_t[C];
    PRF.FillBuffer((uint8_t *)flipped_bits[i], 2 * C, i);
  }

#if !OPTIMAL
  ServerLog("Running first part FSM");
#endif

  int l = 0;
  int smallest_number_of_bits = 0;
  for (int round = 0; round < pArgs.FSM1_rounds; round++)
  {
    uint8_t concurrent_iterations = pArgs.FSM1_steps[round];
    uint8_t all_ones_string = (uint8_t)((1 << concurrent_iterations) - 1);
    uint8_t pow_iterations = (uint8_t)((1 << concurrent_iterations));
    uint8_t pos_states = 2 * pow_iterations;

    if (l >= bits_per_component[smallest_number_of_bits])
    {
      while(l >= bits_per_component[smallest_number_of_bits])
        smallest_number_of_bits ++;
    }
    uint8_t number_of_bit_entries = C - smallest_number_of_bits;

    uint8_t *msgs = new uint8_t[N * number_of_bit_entries * 2 * pow_iterations];

    for (int i = 0; i < N; i++)
    {
      for (int j = 0; j < number_of_bit_entries; j++)
      {
        uint8_t postImageJ = j + C - number_of_bit_entries;

        bool previous_reject = round == 0 ? 1 : !(flipped_bits[i][postImageJ] >> (round - 1) & 0x1);
        bool next_flipped_bit = (flipped_bits[i][postImageJ] >> round) & 0x1;

        uint8_t entry_bits = (db[i][postImageJ] >> l) & all_ones_string;

        for (int state = 0; state < pos_states; state++)
        {
          if (state < (pos_states / 2))
          {
            msgs[number_of_bit_entries * pos_states * i + j * pos_states + state] = (previous_reject != 0 && entry_bits == (state % pow_iterations)) ? next_flipped_bit : !next_flipped_bit;
          }
          else
          {
            msgs[number_of_bit_entries * pos_states * i + j * pos_states + state] = (previous_reject != 1 && entry_bits == (state % pow_iterations)) ? next_flipped_bit : !next_flipped_bit;
          }
        }
      }
    }

#if !OPTIMAL
    ServerLog("Finished creating messages");
#endif

    uint8_t *rMsg = new uint8_t[N * number_of_bit_entries];

    ReceiveLargePacked(socket, 1 + concurrent_iterations, N * number_of_bit_entries, rMsg);

    uint8_t *sMsg = new uint8_t[N * number_of_bit_entries * pos_states];
    ConstructOTSenderMsg(sMsg, *(FSM1_SC[round]), msgs, rMsg, N * number_of_bit_entries, 1);

    SendLargePacked(socket, 1, N * number_of_bit_entries * pos_states, sMsg);

    delete[] msgs;
    delete[] rMsg;
    delete[] sMsg;

    l += concurrent_iterations;
  }

#if !OPTIMAL
  ServerLog("Finished part 1 of the FSM");
#endif
  uint8_t highest_number_of_bits = bits_per_component[C - 1];
  uint8_t **FinalRandomness = new uint8_t *[N];
  for (int i = 0; i < N; i++)
  {
    FinalRandomness[i] = new uint8_t[C];
    for (int j = 0; j < C; j++)
    {
      FinalRandomness[i][j] = (flipped_bits[i][j] >> (pArgs.FSM1_rounds - 1 - ((highest_number_of_bits - bits_per_component[j]) / 2))) & 0x1;
    }
  }

#if !OPTIMAL
  ServerLog("Starting Second FSM");
#endif

  AESContext PRF2;

  uint8_t **random_shift = new uint8_t *[N];
  uint32_t tag_counter = 0;
  for (int i = 0; i < N; i++)
  {
    random_shift[i] = new uint8_t[pArgs.FSM2_rounds];
    PRF2.FillBuffer(random_shift[i], pArgs.FSM2_rounds, tag_counter);
    for (int j = 0; j < pArgs.FSM2_rounds; j++)
    {
      while (random_shift[i][j] == 255)
      {
        tag_counter += 1;
        PRF2.FillBuffer(&random_shift[i][j], 1, tag_counter);
      }
      random_shift[i][j] %= 3;
    }
    tag_counter += 1;
  }

  for (int i = 0; i < N; i++)
    random_shift[i][pArgs.FSM2_rounds - 1] = 0; // Make sure that the final permutation is always 0 to reveal the true state to the client

  uint32_t c = 0;
  for (int round = 0; round < pArgs.FSM2_rounds; round++)
  {
    uint8_t round_step = pArgs.FSM2_steps[round];
    uint8_t round_factor = 1 << round_step;

    uint8_t *msgs = new uint8_t[N * 3 * round_factor];
    for (int i = 0; i < N; i++)
    {
      int previous_shift = (c == 0) ? 0 : random_shift[i][round - 1];
      for (int possible_state = 0; possible_state < 3; possible_state++)
      {
        uint8_t old_state = (possible_state + 3 - previous_shift) % 3;

        uint8_t equality_bits = 0;
        for (int j = 0; j < round_step; j++)
        {
          equality_bits += (FinalRandomness[i][c + j] * (1 << j));
        }

        // equality bits = the best correct state -> having it correct is plus FSM_RC
        // ~equality bits = worst case -> having it correct is plus 0
        //
        for (uint8_t j = 0; j < round_factor; j++)
        {
          uint8_t no_match_count = round_step - count_ones(((~(j ^ equality_bits)) & (round_factor - 1)));
          if (old_state - no_match_count < 0)
            msgs[((3 * round_factor) * i + possible_state * round_factor + j)] = (0 + random_shift[i][round]);
          else
            msgs[((3 * round_factor) * i + possible_state * round_factor + j)] = (old_state - no_match_count + random_shift[i][round]) % 3;
  
        }
      }

    }

#if !OPTIMAL
    ServerLog("Finished one round");
#endif

    

    uint8_t *rMsg = new uint8_t[N];

    ReceiveLargePacked(socket, 2 + round_step, N, rMsg);
    
    uint8_t *sMsg = new uint8_t[N * 3 * round_factor];
    ConstructOTSenderMsg(sMsg, *(FSM2_SC[round]), msgs, rMsg, N, 2);

    SendLargePacked(socket, 2, N * 3 * round_factor, sMsg);

    c += round_step;

    delete[] msgs;
    delete[] rMsg;
    delete[] sMsg;
  }

#if !OPTIMAL
  ServerLog("finished everything");
  cout << "Memory clean up" << endl;
#endif

  for (int i = 0; i < N; i++)
  {
    delete[] db[i];
    delete[] flipped_bits[i];
    delete[] random_shift[i];
    delete[] FinalRandomness[i];
  }
  delete[] db;
  delete[] flipped_bits;
  delete[] random_shift;
  delete[] FinalRandomness;

  for (int i = 0; i < pArgs.FSM1_rounds; i++)
  {
    delete FSM1_SC[i];
  }
  delete[] FSM1_SC;

  for (int i = 0; i < pArgs.FSM2_rounds; i++)
  {
    delete FSM2_SC[i];
  }
  delete[] FSM2_SC;
}

// Assembly:
subq $0xbb8, %rsp            # imm = 0xBB8
movq %rsi, 0x150(%rsp)
movq %rdx, 0x158(%rsp)
movq %rdi, 0xbb0(%rsp)
movq %rsi, 0xba8(%rsp)
movq %rdx, 0xba0(%rsp)
leaq 0xb7f(%rsp), %rdi
movq %rdi, 0x160(%rsp)
callq 0x2420
movq 0x160(%rsp), %rdx
leaq 0x6961(%rip), %rsi      # 0x9004
leaq 0xb80(%rsp), %rdi
callq 0x2350
jmp 0x26b2
leaq 0xb80(%rsp), %rdi
callq 0x3d90
jmp 0x26c1
leaq 0xb80(%rsp), %rdi
callq 0x2170
leaq 0xb7f(%rsp), %rdi
callq 0x22b0
leaq 0x960(%rsp), %rdi
callq 0x22d0
movl $0x8, %edi
movl $0x4, %esi
callq 0x4580
movl %eax, 0x14c(%rsp)
jmp 0x2700
movl 0x14c(%rsp), %edx
movq 0x150(%rsp), %rsi
leaq 0x960(%rsp), %rdi
callq 0x21d0
jmp 0x271e
leaq 0x930(%rsp), %rdi
leaq 0x960(%rsp), %rsi
callq 0x6110
jmp 0x2735
leaq 0x960(%rsp), %rdi
callq 0x2080
jmp 0x2744
leaq 0x728(%rsp), %rdi
callq 0x22d0
jmp 0x2753
movq 0x158(%rsp), %rsi
leaq 0x68bb(%rip), %rdx      # 0x901d
leaq 0x708(%rsp), %rdi
callq 0x45a0
jmp 0x2771
movl $0x8, %edi
movl $0x4, %esi
callq 0x4580
movl %eax, 0x148(%rsp)
jmp 0x2789
movl 0x148(%rsp), %edx
leaq 0x728(%rsp), %rdi
leaq 0x708(%rsp), %rsi
callq 0x21d0
jmp 0x27a7
leaq 0x708(%rsp), %rdi
callq 0x2170
vmovdqu 0x930(%rsp), %ymm0
vmovdqu 0x940(%rsp), %ymm1
vmovdqu %ymm1, 0x6e0(%rsp)
vmovdqu %ymm0, 0x6d0(%rsp)
leaq 0x728(%rsp), %rdi
leaq 0x6d0(%rsp), %rsi
vzeroupper
callq 0x65f0
movq %rax, 0x140(%rsp)
jmp 0x27fa
leaq 0x6d0(%rsp), %rdi
callq 0x62a0
movq 0x140(%rsp), %rax
movq %rax, 0x700(%rsp)
vmovdqu 0x930(%rsp), %ymm0
vmovdqu 0x940(%rsp), %ymm1
vmovdqu %ymm1, 0x6a0(%rsp)
vmovdqu %ymm0, 0x690(%rsp)
leaq 0x728(%rsp), %rdi
leaq 0x690(%rsp), %rsi
vzeroupper
callq 0x66c0
movq %rax, 0x138(%rsp)
jmp 0x285d
leaq 0x690(%rsp), %rdi
callq 0x62a0
movq 0x138(%rsp), %rax
movq %rax, 0x6c8(%rsp)
leaq 0x728(%rsp), %rdi
callq 0x2080
jmp 0x2889
movl 0x930(%rsp), %eax
movl %eax, 0x68c(%rsp)
movl 0x934(%rsp), %eax
movl %eax, 0x688(%rsp)
movq 0x950(%rsp), %rax
movq %rax, 0x680(%rsp)
leaq 0x478(%rsp), %rdi
callq 0x22d0
jmp 0x28c4
movq 0x158(%rsp), %rsi
leaq 0x6752(%rip), %rdx      # 0x9025
leaq 0x458(%rsp), %rdi
callq 0x45a0
jmp 0x28e2
leaq 0x478(%rsp), %rdi
leaq 0x458(%rsp), %rsi
movl $0x8, %edx
callq 0x21d0
jmp 0x28fe
leaq 0x458(%rsp), %rdi
callq 0x2170
movl 0x68c(%rsp), %esi
movl 0x688(%rsp), %edx
leaq 0x478(%rsp), %rdi
callq 0x6b00
movq %rax, 0x130(%rsp)
jmp 0x2930
movq 0x130(%rsp), %rax
movq %rax, 0x450(%rsp)
leaq 0x478(%rsp), %rdi
callq 0x2080
jmp 0x294f
leaq 0x340(%rsp), %rdi
callq 0x7770
jmp 0x295e
movl 0x68c(%rsp), %eax
movl %eax, %edi
shlq $0x3, %rdi
callq 0x2030
movq %rax, 0x128(%rsp)
jmp 0x297a
movq 0x128(%rsp), %rax
movq %rax, 0x338(%rsp)
movl $0x0, 0x334(%rsp)
movl 0x334(%rsp), %eax
cmpl 0x68c(%rsp), %eax
jae 0x2b82
movl 0x688(%rsp), %eax
movl %eax, %edi
addq %rdi, %rdi
callq 0x2030
movq %rax, 0x120(%rsp)
jmp 0x29c4
movq 0x120(%rsp), %rdx
movq 0x338(%rsp), %rax
movslq 0x334(%rsp), %rcx
movq %rdx, (%rax,%rcx,8)
movq 0x338(%rsp), %rax
movslq 0x334(%rsp), %rcx
movq (%rax,%rcx,8), %rsi
movl 0x688(%rsp), %edx
addl %edx, %edx
leaq 0x340(%rsp), %rdi
callq 0x8c40
jmp 0x2a0c
jmp 0x2a0e
movl 0x334(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x334(%rsp)
jmp 0x2995
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb70(%rsp)
movl %eax, 0xb6c(%rsp)
jmp 0x2a5b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb70(%rsp)
movl %eax, 0xb6c(%rsp)
leaq 0xb80(%rsp), %rdi
callq 0x2170
leaq 0xb7f(%rsp), %rdi
callq 0x22b0
jmp 0x3d75
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb70(%rsp)
movl %eax, 0xb6c(%rsp)
jmp 0x3d68
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb70(%rsp)
movl %eax, 0xb6c(%rsp)
jmp 0x3d5b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb70(%rsp)
movl %eax, 0xb6c(%rsp)
jmp 0x3d4e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb70(%rsp)
movl %eax, 0xb6c(%rsp)
leaq 0x708(%rsp), %rdi
callq 0x2170
jmp 0x3d4e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb70(%rsp)
movl %eax, 0xb6c(%rsp)
leaq 0x6d0(%rsp), %rdi
callq 0x62a0
jmp 0x3d4e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb70(%rsp)
movl %eax, 0xb6c(%rsp)
leaq 0x690(%rsp), %rdi
callq 0x62a0
jmp 0x3d4e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb70(%rsp)
movl %eax, 0xb6c(%rsp)
jmp 0x3d41
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb70(%rsp)
movl %eax, 0xb6c(%rsp)
leaq 0x458(%rsp), %rdi
callq 0x2170
jmp 0x3d41
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb70(%rsp)
movl %eax, 0xb6c(%rsp)
jmp 0x3d34
movl $0x0, 0x330(%rsp)
movl $0x0, 0x32c(%rsp)
movl $0x0, 0x328(%rsp)
movl 0x328(%rsp), %eax
cmpl 0x938(%rsp), %eax
jae 0x31bc
movq 0x940(%rsp), %rax
movslq 0x328(%rsp), %rcx
movb (%rax,%rcx), %al
movb %al, 0x327(%rsp)
movzbl 0x327(%rsp), %ecx
movl $0x1, %eax
shll %cl, %eax
subl $0x1, %eax
movb %al, 0x326(%rsp)
movzbl 0x327(%rsp), %ecx
movl $0x1, %eax
shll %cl, %eax
movb %al, 0x325(%rsp)
movzbl 0x325(%rsp), %eax
shll %eax
movb %al, 0x324(%rsp)
movl 0x330(%rsp), %eax
movq 0x680(%rsp), %rcx
movslq 0x32c(%rsp), %rdx
movzbl (%rcx,%rdx), %ecx
cmpl %ecx, %eax
jl 0x2c66
jmp 0x2c32
movl 0x330(%rsp), %eax
movq 0x680(%rsp), %rcx
movslq 0x32c(%rsp), %rdx
movzbl (%rcx,%rdx), %ecx
cmpl %ecx, %eax
jl 0x2c64
movl 0x32c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x32c(%rsp)
jmp 0x2c32
jmp 0x2c66
movl 0x688(%rsp), %eax
movl 0x32c(%rsp), %ecx
subl %ecx, %eax
movb %al, 0x323(%rsp)
movl 0x68c(%rsp), %eax
movzbl 0x323(%rsp), %ecx
imull %ecx, %eax
movzbl 0x325(%rsp), %ecx
imull %ecx, %eax
addl %eax, %eax
movl %eax, %edi
callq 0x2030
movq %rax, 0x118(%rsp)
jmp 0x2cad
movq 0x118(%rsp), %rax
movq %rax, 0x318(%rsp)
movl $0x0, 0x314(%rsp)
movl 0x314(%rsp), %eax
cmpl 0x68c(%rsp), %eax
jae 0x2ff6
movl $0x0, 0x310(%rsp)
movl 0x310(%rsp), %eax
movzbl 0x323(%rsp), %ecx
cmpl %ecx, %eax
jge 0x2fde
movl 0x310(%rsp), %eax
addl 0x688(%rsp), %eax
movzbl 0x323(%rsp), %ecx
subl %ecx, %eax
movb %al, 0x30f(%rsp)
cmpl $0x0, 0x328(%rsp)
jne 0x2d35
movl $0x1, %eax
movl %eax, 0x114(%rsp)
jmp 0x2d78
movq 0x338(%rsp), %rax
movslq 0x314(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movzbl 0x30f(%rsp), %ecx
movzwl (%rax,%rcx,2), %eax
movl 0x328(%rsp), %ecx
subl $0x1, %ecx
sarl %cl, %eax
andl $0x1, %eax
cmpl $0x0, %eax
setne %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x114(%rsp)
movl 0x114(%rsp), %eax
cmpl $0x0, %eax
setne %al
andb $0x1, %al
movb %al, 0x30e(%rsp)
movq 0x338(%rsp), %rax
movslq 0x314(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movzbl 0x30f(%rsp), %ecx
movzwl (%rax,%rcx,2), %eax
movl 0x328(%rsp), %ecx
sarl %cl, %eax
andl $0x1, %eax
cmpl $0x0, %eax
setne %al
andb $0x1, %al
movb %al, 0x30d(%rsp)
movq 0x450(%rsp), %rax
movslq 0x314(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movzbl 0x30f(%rsp), %ecx
movl (%rax,%rcx,4), %eax
movl 0x330(%rsp), %ecx
shrl %cl, %eax
movzbl 0x326(%rsp), %ecx
andl %ecx, %eax
movb %al, 0x30c(%rsp)
movl $0x0, 0x308(%rsp)
movl 0x308(%rsp), %eax
movzbl 0x324(%rsp), %ecx
cmpl %ecx, %eax
jge 0x2fc6
movl 0x308(%rsp), %eax
movl %eax, 0x110(%rsp)
movzbl 0x324(%rsp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movl 0x110(%rsp), %eax
cmpl %ecx, %eax
jge 0x2f03
movb 0x30e(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
je 0x2ea0
movzbl 0x30c(%rsp), %eax
movl %eax, 0x10c(%rsp)
movl 0x308(%rsp), %eax
movzbl 0x325(%rsp), %ecx
cltd
idivl %ecx
movl 0x10c(%rsp), %eax
cmpl %edx, %eax
jne 0x2ea0
movb 0x30d(%rsp), %al
movb %al, 0x10b(%rsp)
jmp 0x2eb0
movb 0x30d(%rsp), %al
xorb $-0x1, %al
movb %al, 0x10b(%rsp)
movb 0x10b(%rsp), %dl
andb $0x1, %dl
movq 0x318(%rsp), %rax
movzbl 0x323(%rsp), %ecx
movzbl 0x324(%rsp), %esi
imull %esi, %ecx
imull 0x314(%rsp), %ecx
movl 0x310(%rsp), %esi
movzbl 0x324(%rsp), %edi
imull %edi, %esi
addl %esi, %ecx
addl 0x308(%rsp), %ecx
movslq %ecx, %rcx
movb %dl, (%rax,%rcx)
jmp 0x2fae
movb 0x30e(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x1, %eax
je 0x2f50
movzbl 0x30c(%rsp), %eax
movl %eax, 0x104(%rsp)
movl 0x308(%rsp), %eax
movzbl 0x325(%rsp), %ecx
cltd
idivl %ecx
movl 0x104(%rsp), %eax
cmpl %edx, %eax
jne 0x2f50
movb 0x30d(%rsp), %al
movb %al, 0x103(%rsp)
jmp 0x2f60
movb 0x30d(%rsp), %al
xorb $-0x1, %al
movb %al, 0x103(%rsp)
movb 0x103(%rsp), %dl
andb $0x1, %dl
movq 0x318(%rsp), %rax
movzbl 0x323(%rsp), %ecx
movzbl 0x324(%rsp), %esi
imull %esi, %ecx
imull 0x314(%rsp), %ecx
movl 0x310(%rsp), %esi
movzbl 0x324(%rsp), %edi
imull %edi, %esi
addl %esi, %ecx
addl 0x308(%rsp), %ecx
movslq %ecx, %rcx
movb %dl, (%rax,%rcx)
jmp 0x2fb0
movl 0x308(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x308(%rsp)
jmp 0x2e0d
jmp 0x2fc8
movl 0x310(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x310(%rsp)
jmp 0x2ce7
jmp 0x2fe0
movl 0x314(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x314(%rsp)
jmp 0x2cc8
movl 0x68c(%rsp), %eax
movzbl 0x323(%rsp), %ecx
imull %ecx, %eax
movl %eax, %edi
callq 0x2030
movq %rax, 0xf8(%rsp)
jmp 0x3019
movq 0xf8(%rsp), %rax
movq %rax, 0x300(%rsp)
movq 0xbb0(%rsp), %rdi
movzbl 0x327(%rsp), %eax
incl %eax
movl 0x68c(%rsp), %ecx
movzbl 0x323(%rsp), %edx
imull %edx, %ecx
movl %ecx, %edx
movq 0x300(%rsp), %rcx
movzbl %al, %esi
callq 0x6d50
jmp 0x3061
movl 0x68c(%rsp), %eax
movzbl 0x323(%rsp), %ecx
imull %ecx, %eax
movzbl 0x324(%rsp), %ecx
imull %ecx, %eax
movl %eax, %edi
callq 0x2030
movq %rax, 0xf0(%rsp)
jmp 0x308f
movq 0xf0(%rsp), %rax
movq %rax, 0x2f8(%rsp)
movq 0x2f8(%rsp), %rdi
movq 0x700(%rsp), %rax
movslq 0x328(%rsp), %rcx
movq (%rax,%rcx,8), %rsi
movq 0x318(%rsp), %rdx
movq 0x300(%rsp), %rcx
movl 0x68c(%rsp), %r8d
movzbl 0x323(%rsp), %eax
imull %eax, %r8d
movl $0x1, %r9d
callq 0x5280
jmp 0x30ec
movq 0xbb0(%rsp), %rdi
movl 0x68c(%rsp), %eax
movzbl 0x323(%rsp), %ecx
imull %ecx, %eax
movzbl 0x324(%rsp), %ecx
imull %ecx, %eax
movl %eax, %edx
movq 0x2f8(%rsp), %rcx
movl $0x1, %esi
callq 0x6b90
jmp 0x3127
movq 0x318(%rsp), %rax
movq %rax, 0xe8(%rsp)
cmpq $0x0, %rax
je 0x314a
movq 0xe8(%rsp), %rdi
callq 0x2320
movq 0x300(%rsp), %rax
movq %rax, 0xe0(%rsp)
cmpq $0x0, %rax
je 0x316d
movq 0xe0(%rsp), %rdi
callq 0x2320
movq 0x2f8(%rsp), %rax
movq %rax, 0xd8(%rsp)
cmpq $0x0, %rax
je 0x3190
movq 0xd8(%rsp), %rdi
callq 0x2320
movzbl 0x327(%rsp), %eax
addl 0x330(%rsp), %eax
movl %eax, 0x330(%rsp)
movl 0x328(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x328(%rsp)
jmp 0x2ba3
movq 0x680(%rsp), %rax
movl 0x688(%rsp), %ecx
decl %ecx
movb (%rax,%rcx), %al
movb %al, 0x2f7(%rsp)
movl 0x68c(%rsp), %eax
movl %eax, %edi
shlq $0x3, %rdi
callq 0x2030
movq %rax, 0xd0(%rsp)
jmp 0x31f3
movq 0xd0(%rsp), %rax
movq %rax, 0x2e8(%rsp)
movl $0x0, 0x2e4(%rsp)
movl 0x2e4(%rsp), %eax
cmpl 0x68c(%rsp), %eax
jae 0x332b
movl 0x688(%rsp), %eax
movl %eax, %edi
callq 0x2030
movq %rax, 0xc8(%rsp)
jmp 0x323a
movq 0xc8(%rsp), %rdx
movq 0x2e8(%rsp), %rax
movslq 0x2e4(%rsp), %rcx
movq %rdx, (%rax,%rcx,8)
movl $0x0, 0x2e0(%rsp)
movl 0x2e0(%rsp), %eax
cmpl 0x688(%rsp), %eax
jae 0x3313
movq 0x338(%rsp), %rax
movslq 0x2e4(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movslq 0x2e0(%rsp), %rcx
movzwl (%rax,%rcx,2), %eax
movl %eax, 0xc4(%rsp)
movl 0x938(%rsp), %ecx
subl $0x1, %ecx
movzbl 0x2f7(%rsp), %eax
movq 0x680(%rsp), %rdx
movslq 0x2e0(%rsp), %rsi
movzbl (%rdx,%rsi), %edx
subl %edx, %eax
movl $0x2, %esi
cltd
idivl %esi
movl %eax, %edx
movl 0xc4(%rsp), %eax
subl %edx, %ecx
sarl %cl, %eax
andl $0x1, %eax
movb %al, %dl
movq 0x2e8(%rsp), %rax
movslq 0x2e4(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movslq 0x2e0(%rsp), %rcx
movb %dl, (%rax,%rcx)
movl 0x2e0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2e0(%rsp)
jmp 0x3261
jmp 0x3315
movl 0x2e4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2e4(%rsp)
jmp 0x320e
leaq 0x1d0(%rsp), %rdi
callq 0x7770
jmp 0x333a
movl 0x68c(%rsp), %eax
movl %eax, %edi
shlq $0x3, %rdi
callq 0x2030
movq %rax, 0xb8(%rsp)
jmp 0x3356
movq 0xb8(%rsp), %rax
movq %rax, 0x1c8(%rsp)
movl $0x0, 0x1c4(%rsp)
movl $0x0, 0x1c0(%rsp)
movl 0x1c0(%rsp), %eax
cmpl 0x68c(%rsp), %eax
jae 0x352b
movl 0x93c(%rsp), %eax
movl %eax, %edi
callq 0x2030
movq %rax, 0xb0(%rsp)
jmp 0x33a8
movq 0xb0(%rsp), %rdx
movq 0x1c8(%rsp), %rax
movslq 0x1c0(%rsp), %rcx
movq %rdx, (%rax,%rcx,8)
movq 0x1c8(%rsp), %rax
movslq 0x1c0(%rsp), %rcx
movq (%rax,%rcx,8), %rsi
movl 0x93c(%rsp), %edx
movl 0x1c4(%rsp), %eax
movl %eax, %ecx
leaq 0x1d0(%rsp), %rdi
callq 0x8c40
jmp 0x33f7
movl $0x0, 0x1bc(%rsp)
movl 0x1bc(%rsp), %eax
cmpl 0x93c(%rsp), %eax
jae 0x3504
jmp 0x3418
movq 0x1c8(%rsp), %rax
movslq 0x1c0(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movslq 0x1bc(%rsp), %rcx
movzbl (%rax,%rcx), %eax
cmpl $0xff, %eax
jne 0x34b3
movl 0x1c4(%rsp), %eax
incl %eax
movl %eax, 0x1c4(%rsp)
movq 0x1c8(%rsp), %rax
movslq 0x1c0(%rsp), %rcx
movq (%rax,%rcx,8), %rsi
movslq 0x1bc(%rsp), %rax
addq %rax, %rsi
movl 0x1c4(%rsp), %eax
movl %eax, %ecx
leaq 0x1d0(%rsp), %rdi
movl $0x1, %edx
callq 0x8c40
jmp 0x348b
jmp 0x3418
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb70(%rsp)
movl %eax, 0xb6c(%rsp)
leaq 0x1d0(%rsp), %rdi
callq 0x87a0
jmp 0x3d34
movq 0x1c8(%rsp), %rax
movslq 0x1c0(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, 0xa8(%rsp)
movslq 0x1bc(%rsp), %rcx
movzbl (%rax,%rcx), %eax
movl $0x3, %esi
cltd
idivl %esi
movq 0xa8(%rsp), %rax
movb %dl, (%rax,%rcx)
movl 0x1bc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1bc(%rsp)
jmp 0x3402
movl 0x1c4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1c4(%rsp)
movl 0x1c0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1c0(%rsp)
jmp 0x337c
movl $0x0, 0x1b8(%rsp)
movl 0x1b8(%rsp), %eax
cmpl 0x68c(%rsp), %eax
jae 0x357d
movq 0x1c8(%rsp), %rax
movslq 0x1b8(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movl 0x93c(%rsp), %ecx
subl $0x1, %ecx
movl %ecx, %ecx
movb $0x0, (%rax,%rcx)
movl 0x1b8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1b8(%rsp)
jmp 0x3536
movl $0x0, 0x1b4(%rsp)
movl $0x0, 0x1b0(%rsp)
movl 0x1b0(%rsp), %eax
cmpl 0x93c(%rsp), %eax
jae 0x3a8f
movq 0x948(%rsp), %rax
movslq 0x1b0(%rsp), %rcx
movb (%rax,%rcx), %al
movb %al, 0x1af(%rsp)
movb 0x1af(%rsp), %al
movb %al, %cl
movl $0x1, %eax
shlxl %ecx, %eax, %eax
movb %al, 0x1ae(%rsp)
movl 0x68c(%rsp), %ecx
movzbl 0x1ae(%rsp), %eax
imull %eax, %ecx
movl %ecx, %eax
leal (%rax,%rax,2), %eax
movl %eax, %edi
callq 0x2030
movq %rax, 0xa0(%rsp)
jmp 0x3603
movq 0xa0(%rsp), %rax
movq %rax, 0x1a0(%rsp)
movl $0x0, 0x19c(%rsp)
movl 0x19c(%rsp), %eax
cmpl 0x68c(%rsp), %eax
jae 0x3906
cmpl $0x0, 0x1b4(%rsp)
jne 0x3647
xorl %eax, %eax
movl %eax, 0x9c(%rsp)
jmp 0x3673
movq 0x1c8(%rsp), %rax
movslq 0x19c(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movl 0x1b0(%rsp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movzbl (%rax,%rcx), %eax
movl %eax, 0x9c(%rsp)
movl 0x9c(%rsp), %eax
movl %eax, 0x198(%rsp)
movl $0x0, 0x194(%rsp)
cmpl $0x3, 0x194(%rsp)
jge 0x38ee
movl 0x194(%rsp), %eax
addl $0x3, %eax
subl 0x198(%rsp), %eax
movl $0x3, %ecx
cltd
idivl %ecx
movb %dl, %al
movb %al, 0x193(%rsp)
movb $0x0, 0x192(%rsp)
movl $0x0, 0x18c(%rsp)
movl 0x18c(%rsp), %eax
movzbl 0x1af(%rsp), %ecx
cmpl %ecx, %eax
jge 0x374d
movq 0x2e8(%rsp), %rax
movslq 0x19c(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movl 0x1b4(%rsp), %ecx
addl 0x18c(%rsp), %ecx
movl %ecx, %ecx
movzbl (%rax,%rcx), %eax
movl %eax, 0x98(%rsp)
movl 0x18c(%rsp), %ecx
movl $0x1, %eax
shll %cl, %eax
movl 0x98(%rsp), %ecx
imull %eax, %ecx
movzbl 0x192(%rsp), %eax
addl %ecx, %eax
movb %al, 0x192(%rsp)
movl 0x18c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x18c(%rsp)
jmp 0x36cf
movb $0x0, 0x18b(%rsp)
movzbl 0x18b(%rsp), %eax
movzbl 0x1ae(%rsp), %ecx
cmpl %ecx, %eax
jge 0x38d6
movzbl 0x1af(%rsp), %eax
movl %eax, 0x90(%rsp)
movzbl 0x18b(%rsp), %eax
movzbl 0x192(%rsp), %ecx
xorl %ecx, %eax
xorl $0xff, %eax
movzbl 0x1ae(%rsp), %edi
decl %edi
andl %eax, %edi
callq 0x6930
movb %al, 0x97(%rsp)
jmp 0x37ad
movl 0x90(%rsp), %eax
movb 0x97(%rsp), %cl
movzbl %cl, %ecx
subl %ecx, %eax
movb %al, 0x18a(%rsp)
movzbl 0x193(%rsp), %eax
movzbl 0x18a(%rsp), %ecx
subl %ecx, %eax
cmpl $0x0, %eax
jge 0x3844
movq 0x1c8(%rsp), %rax
movslq 0x19c(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movslq 0x1b0(%rsp), %rcx
movzbl (%rax,%rcx), %eax
addl $0x0, %eax
movb %al, %dl
movq 0x1a0(%rsp), %rax
movzbl 0x1ae(%rsp), %ecx
imull $0x3, %ecx, %ecx
imull 0x19c(%rsp), %ecx
movl 0x194(%rsp), %esi
movzbl 0x1ae(%rsp), %edi
imull %edi, %esi
addl %esi, %ecx
movzbl 0x18b(%rsp), %esi
addl %esi, %ecx
movslq %ecx, %rcx
movb %dl, (%rax,%rcx)
jmp 0x38bf
movzbl 0x193(%rsp), %eax
movzbl 0x18a(%rsp), %ecx
subl %ecx, %eax
movq 0x1c8(%rsp), %rcx
movslq 0x19c(%rsp), %rdx
movq (%rcx,%rdx,8), %rcx
movslq 0x1b0(%rsp), %rdx
movzbl (%rcx,%rdx), %ecx
addl %ecx, %eax
movl $0x3, %ecx
cltd
idivl %ecx
movq 0x1a0(%rsp), %rax
movzbl 0x1ae(%rsp), %ecx
imull $0x3, %ecx, %ecx
imull 0x19c(%rsp), %ecx
movl 0x194(%rsp), %esi
movzbl 0x1ae(%rsp), %edi
imull %edi, %esi
addl %esi, %ecx
movzbl 0x18b(%rsp), %esi
addl %esi, %ecx
movslq %ecx, %rcx
movb %dl, (%rax,%rcx)
jmp 0x38c1
movb 0x18b(%rsp), %al
addb $0x1, %al
movb %al, 0x18b(%rsp)
jmp 0x3755
jmp 0x38d8
movl 0x194(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x194(%rsp)
jmp 0x368c
jmp 0x38f0
movl 0x19c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x19c(%rsp)
jmp 0x361e
movl 0x68c(%rsp), %eax
movl %eax, %edi
callq 0x2030
movq %rax, 0x88(%rsp)
jmp 0x391e
movq 0x88(%rsp), %rax
movq %rax, 0x180(%rsp)
movq 0xbb0(%rsp), %rdi
movzbl 0x1af(%rsp), %eax
addl $0x2, %eax
movl 0x68c(%rsp), %ecx
movl %ecx, %edx
movq 0x180(%rsp), %rcx
movzbl %al, %esi
callq 0x6d50
jmp 0x395c
movl 0x68c(%rsp), %ecx
movzbl 0x1ae(%rsp), %eax
imull %eax, %ecx
movl %ecx, %eax
leal (%rax,%rax,2), %eax
movl %eax, %edi
callq 0x2030
movq %rax, 0x80(%rsp)
jmp 0x3984
movq 0x80(%rsp), %rax
movq %rax, 0x178(%rsp)
movq 0x178(%rsp), %rdi
movq 0x6c8(%rsp), %rax
movslq 0x1b0(%rsp), %rcx
movq (%rax,%rcx,8), %rsi
movq 0x1a0(%rsp), %rdx
movq 0x180(%rsp), %rcx
movl 0x68c(%rsp), %r8d
movl $0x2, %r9d
callq 0x5280
jmp 0x39d5
movq 0xbb0(%rsp), %rdi
movl 0x68c(%rsp), %ecx
movzbl 0x1ae(%rsp), %eax
imull %eax, %ecx
movl %ecx, %eax
leal (%rax,%rax,2), %eax
movl %eax, %edx
movq 0x178(%rsp), %rcx
movl $0x2, %esi
callq 0x6b90
jmp 0x3a0a
movzbl 0x1af(%rsp), %eax
addl 0x1b4(%rsp), %eax
movl %eax, 0x1b4(%rsp)
movq 0x1a0(%rsp), %rax
movq %rax, 0x78(%rsp)
cmpq $0x0, %rax
je 0x3a3d
movq 0x78(%rsp), %rdi
callq 0x2320
movq 0x180(%rsp), %rax
movq %rax, 0x70(%rsp)
cmpq $0x0, %rax
je 0x3a5a
movq 0x70(%rsp), %rdi
callq 0x2320
movq 0x178(%rsp), %rax
movq %rax, 0x68(%rsp)
cmpq $0x0, %rax
je 0x3a77
movq 0x68(%rsp), %rdi
callq 0x2320
jmp 0x3a79
movl 0x1b0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1b0(%rsp)
jmp 0x3593
movl $0x0, 0x174(%rsp)
movl 0x174(%rsp), %eax
cmpl 0x68c(%rsp), %eax
jae 0x3b6a
movq 0x450(%rsp), %rax
movslq 0x174(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, 0x60(%rsp)
cmpq $0x0, %rax
je 0x3ad7
movq 0x60(%rsp), %rdi
callq 0x2320
movq 0x338(%rsp), %rax
movslq 0x174(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, 0x58(%rsp)
cmpq $0x0, %rax
je 0x3b00
movq 0x58(%rsp), %rdi
callq 0x2320
movq 0x1c8(%rsp), %rax
movslq 0x174(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, 0x50(%rsp)
cmpq $0x0, %rax
je 0x3b29
movq 0x50(%rsp), %rdi
callq 0x2320
movq 0x2e8(%rsp), %rax
movslq 0x174(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, 0x48(%rsp)
cmpq $0x0, %rax
je 0x3b52
movq 0x48(%rsp), %rdi
callq 0x2320
jmp 0x3b54
movl 0x174(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x174(%rsp)
jmp 0x3a9a
movq 0x450(%rsp), %rax
movq %rax, 0x40(%rsp)
cmpq $0x0, %rax
je 0x3b87
movq 0x40(%rsp), %rdi
callq 0x2320
movq 0x338(%rsp), %rax
movq %rax, 0x38(%rsp)
cmpq $0x0, %rax
je 0x3ba4
movq 0x38(%rsp), %rdi
callq 0x2320
movq 0x1c8(%rsp), %rax
movq %rax, 0x30(%rsp)
cmpq $0x0, %rax
je 0x3bc1
movq 0x30(%rsp), %rdi
callq 0x2320
movq 0x2e8(%rsp), %rax
movq %rax, 0x28(%rsp)
cmpq $0x0, %rax
je 0x3bde
movq 0x28(%rsp), %rdi
callq 0x2320
movl $0x0, 0x170(%rsp)
movl 0x170(%rsp), %eax
cmpl 0x938(%rsp), %eax
jae 0x3c41
movq 0x700(%rsp), %rax
movslq 0x170(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, 0x20(%rsp)
cmpq $0x0, %rax
je 0x3c2c
movq 0x20(%rsp), %rdi
callq 0x4be0
movq 0x20(%rsp), %rdi
callq 0x2220
jmp 0x3c2e
movl 0x170(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x170(%rsp)
jmp 0x3be9
movq 0x700(%rsp), %rax
movq %rax, 0x18(%rsp)
cmpq $0x0, %rax
je 0x3c5e
movq 0x18(%rsp), %rdi
callq 0x2320
movl $0x0, 0x16c(%rsp)
movl 0x16c(%rsp), %eax
cmpl 0x93c(%rsp), %eax
jae 0x3cc1
movq 0x6c8(%rsp), %rax
movslq 0x16c(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, 0x10(%rsp)
cmpq $0x0, %rax
je 0x3cac
movq 0x10(%rsp), %rdi
callq 0x4be0
movq 0x10(%rsp), %rdi
callq 0x2220
jmp 0x3cae
movl 0x16c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x16c(%rsp)
jmp 0x3c69
movq 0x6c8(%rsp), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, %rax
je 0x3cde
movq 0x8(%rsp), %rdi
callq 0x2320
leaq 0x1d0(%rsp), %rdi
callq 0x87a0
leaq 0x340(%rsp), %rdi
callq 0x87a0
leaq 0x478(%rsp), %rdi
callq 0x20b0
leaq 0x728(%rsp), %rdi
callq 0x20b0
leaq 0x930(%rsp), %rdi
callq 0x62a0
leaq 0x960(%rsp), %rdi
callq 0x20b0
addq $0xbb8, %rsp            # imm = 0xBB8
retq
leaq 0x340(%rsp), %rdi
callq 0x87a0
leaq 0x478(%rsp), %rdi
callq 0x20b0
leaq 0x728(%rsp), %rdi
callq 0x20b0
leaq 0x930(%rsp), %rdi
callq 0x62a0
leaq 0x960(%rsp), %rdi
callq 0x20b0
movq 0xb70(%rsp), %rdi
callq 0x2410
nopw %cs:(%rax,%rax)