// File: cpearce[P]OggIndex/src/Validate.cpp
// Function: ValidateIndexedOgg(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&)
bool ValidateIndexedOgg(const string& filename) {
  ifstream input(filename.c_str(), ios::in | ios::binary);
  ogg_sync_state state;
  ogg_int32_t ret = ogg_sync_init(&state);
  assert(ret==0);

  VerifyDecoderMap decoders;
  ogg_page page;
  memset(&page, 0, sizeof(ogg_page));
  ogg_uint64_t bytesRead = 0;
  Theora* theora = 0;
  Vorbis* vorbis = 0;
  Kate* kate = 0;
  Skeleton* skeleton = 0;
  bool index_valid = true;
  ogg_uint64_t contentOffset = 0;
  
  while (!ReadAllHeaders(theora, vorbis, kate, skeleton) && 
         ReadPage(&state, &page, input, bytesRead))
  {
    contentOffset += page.header_len + page.body_len;
    int serialno = ogg_page_serialno(&page);
    VerifyDecoder* decoder = 0;
    if (ogg_page_bos(&page)) {
      if (page.body_len > 8 &&
          strncmp("theora", (const char*)page.body+1, 6) == 0)
      {
        theora = new Theora(serialno);
        decoders[serialno] = theora;
      } else if (page.body_len > 8 &&
                 strncmp("vorbis", (const char*)page.body+1, 6) == 0)
      {
        vorbis = new Vorbis(serialno);
        decoders[serialno] = vorbis;
#ifdef HAVE_KATE
      } else if (page.body_len > 8 &&
                 memcmp("kate\0\0\0", (const char*)page.body+1, 7) == 0)
      {
        kate = new Kate(serialno);
        decoders[serialno] = kate;
#endif
      } else if (page.body_len > 8 &&
                 strncmp("fishead", (const char*)page.body, 8) == 0)
      {
        skeleton = new Skeleton(serialno);
        decoders[serialno] = skeleton;
      }
    }
    decoder = decoders[serialno];
    if (!decoder) {
      cout << "WARNING: Unknown stream type, serialno=" << serialno << endl;
      continue;
    }
    ogg_int64_t ignore;
    if (!decoder->Decode(&page, ignore)) {
      index_valid = false;
    }
  }

  if (!skeleton) {
    cerr << "FAIL: No skeleton track so therefore no keyframe indexes!" << endl;
    return false;
  }

  if (skeleton->mContentOffset != contentOffset) {
    cerr << "FAIL: skeleton header's reported content offset (" << skeleton->mContentOffset
         << ") does not match actual content offset (" << contentOffset << ")" << endl;
    index_valid = false;
  }

  ogg_int64_t fileLength = FileLength(filename.c_str());
  if (skeleton->mFileLength != fileLength) {
    cerr << "FAIL: index's reported file length (" << skeleton->mFileLength
         << ") doesn't match file's actual length (" << fileLength << ")" << endl;
    index_valid = false;
  }

  KeyFrameIndex::iterator itr = skeleton->mIndex.begin();
  if (itr == skeleton->mIndex.end()) {
    cerr << "WARNING: No tracks in skeleton index." << endl;
  }

  while (itr != skeleton->mIndex.end()) {
    vector<KeyFrameInfo>* v = itr->second;
    ogg_uint32_t serialno = itr->first;
    itr++;
    VerifyDecoder* decoder = decoders[serialno];

    if (!decoder) {
      cerr << "WARNING: No decoder for track s="
           << serialno << endl;
      continue;
    }

    if (v->size() == 0) {
      cerr << "WARNING: " << decoder->Type() << "/" <<  serialno
           << " index has no keyframes" << endl;
      continue;
    }

    cout << decoder->Type() << "/" << serialno
         << " index has " << v->size() << " keypoints." << endl;

    bool valid = true;
    for (ogg_uint32_t i=0; i<v->size(); i++) {
    
      KeyFrameInfo& keypoint = v->at(i);
      if (keypoint.mOffset > INT_MAX) {
        cerr << "WARNING: Only verified up to 2^31 bytes into the file." << endl;
        break;
      }
      
      if (keypoint.mOffset > fileLength) {
        valid = false;
        cerr << "FAIL: Keypoint " << i << " offset of " << keypoint.mOffset
             << " out of file range." << endl;
        break;
      }

      // Check that the checksum of the page here matches, and that the
      // presentation time of the stream matches what's reported in the index.
      ogg_sync_reset(&state);
      if (input.eof()) {
        // Probably hit eof while reading pages for previous keypoint.
        input.close();
        input.clear();        
        input.open(filename.c_str(), ios::in | ios::binary);
      }
      input.seekg(keypoint.mOffset);
      if (!input.good()) {
        cerr << "FAIL: Can't seek to keypoint at byte offset " << keypoint.mOffset << endl;
        return false;
      }
      decoder->Reset();
      ogg_int64_t pres_time = -1;
      ogg_int64_t page_offset = keypoint.mOffset;
      ogg_int64_t end_time = -1;
      while (pres_time  == -1) {
        int skip = 0;
        if ((skip = PageSeek(&state, &page, input, bytesRead)) != 0) {
          if (skip == -1) {
            cerr << "FAIL: Can't read page at offset " << page_offset << endl;
            return false;
          }
          assert(skip > 0);
          cerr << "FAIL: There's no page at offset " << page_offset
               << " as reported by keypoint. Next page is at offset "
               << (page_offset + skip) << endl;
          return false;
        }
        page_offset += page.header_len + page.body_len;
        // Extract the presentation time. Decode() returns -1 if it needs
        // another page.
        if ((ogg_uint32_t)ogg_page_serialno(&page) != decoder->mSerial) {
          // Skip until we read another page on this stream.
          continue;
        }
        pres_time = decoder->Decode(&page, end_time);
        // Vorbis decoders should never return -1 for prestime, it should be
        // calculable from only one page.
        assert(decoder != vorbis || pres_time != -1);
      }

      // We consider a theora the key point is invalid if it's reported time
      // doesn't match the presentation time of the first keyframe which
      // can be decoded from this page.
      if (decoder == theora && keypoint.mTime != pres_time) {
        cerr << "FAIL: theora keypoint " << i << " for page at offset "
             << keypoint.mOffset << " reports start time of "
             << keypoint.mTime << " but should be " << pres_time << endl;
        valid = false;
      }

      // A vorbis keypoint is considered invalid if lies before the start time
      // of this page, or after the end time.
      if (decoder == vorbis &&
          (keypoint.mTime < pres_time || keypoint.mTime > end_time))
      {
        cerr << "FAIL: vorbis keypoint " << i << " for page at offset "
             << keypoint.mOffset << " reports start time of "
             << keypoint.mTime << " but should lie in the range ["
             << pres_time << "," << end_time << "]" << endl;
        valid = false;
      }

#ifdef HAVE_KATE
      if (decoder == kate) {
        // We get the granpos of the page linked to, and check that the base part of the granpos
        // is higher or equal to the time of the keypoint
        ogg_int64_t base_time = kate->GetBaseTime(&page);
        if (base_time > pres_time) {
          cerr << "FAIL: kate keypoint " << i << " for page at offset "
               << keypoint.mOffset << " reports start time of "
               << keypoint.mTime << " but should be greater of equal to "
               << base_time << endl;
          valid = false;
        }
      }
#endif
    }
    if (valid) {
      cout << decoder->Type() << "/" << serialno
           << " index is accurate." << endl;
    } else {
      cout << "FAIL: " << decoder->Type() << "/" << serialno
           << " index is NOT accurate." << endl;
      index_valid = false;
    }
  }

  ogg_sync_clear(&state);
  
  return index_valid;
}

// Assembly:
subq $0x6a8, %rsp            # imm = 0x6A8
movq %rdi, 0x698(%rsp)
movq 0x698(%rsp), %rdi
callq 0x5180
movq %rax, 0x318(%rsp)
movl $0x8, %edi
movl $0x4, %esi
callq 0xe9f0
movq 0x318(%rsp), %rsi
movl %eax, %edx
leaq 0x490(%rsp), %rdi
callq 0x5840
leaq 0x470(%rsp), %rdi
callq 0x51b0
movl %eax, 0x320(%rsp)
jmp 0x17a50
movl 0x320(%rsp), %eax
movl %eax, 0x46c(%rsp)
cmpl $0x0, 0x46c(%rsp)
jne 0x17a6a
jmp 0x17aa2
leaq 0x5e1f(%rip), %rdi      # 0x1d890
leaq 0x6ecf(%rip), %rsi      # 0x1e947
movl $0x21f, %edx            # imm = 0x21F
leaq 0x6ed4(%rip), %rcx      # 0x1e958
callq 0x5280
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x460(%rsp)
movl %eax, 0x45c(%rsp)
jmp 0x19046
leaq 0x428(%rsp), %rdi
callq 0x19100
leaq 0x408(%rsp), %rdi
xorl %esi, %esi
movl $0x20, %edx
callq 0x5230
movq $0x0, 0x400(%rsp)
movq $0x0, 0x3f8(%rsp)
movq $0x0, 0x3f0(%rsp)
movq $0x0, 0x3e8(%rsp)
movq $0x0, 0x3e0(%rsp)
movb $0x1, 0x3df(%rsp)
movq $0x0, 0x3d0(%rsp)
movq 0x3f8(%rsp), %rdi
movq 0x3f0(%rsp), %rsi
movq 0x3e8(%rsp), %rdx
movq 0x3e0(%rsp), %rcx
callq 0x19060
movb %al, 0x317(%rsp)
jmp 0x17b41
movb 0x317(%rsp), %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, 0x316(%rsp)
jne 0x17b96
jmp 0x17b58
leaq 0x470(%rsp), %rdi
leaq 0x408(%rsp), %rsi
leaq 0x490(%rsp), %rdx
leaq 0x400(%rsp), %rcx
callq 0x15f20
movb %al, 0x315(%rsp)
jmp 0x17b86
movb 0x315(%rsp), %al
movb %al, 0x316(%rsp)
jmp 0x17b96
movb 0x316(%rsp), %al
testb $0x1, %al
jne 0x17ba6
jmp 0x17fee
movq 0x410(%rsp), %rcx
movq 0x420(%rsp), %rax
addq %rax, %rcx
movq 0x3d0(%rsp), %rax
addq %rcx, %rax
movq %rax, 0x3d0(%rsp)
leaq 0x408(%rsp), %rdi
callq 0x5350
movl %eax, 0x310(%rsp)
jmp 0x17be2
movl 0x310(%rsp), %eax
movl %eax, 0x3cc(%rsp)
movq $0x0, 0x3c0(%rsp)
leaq 0x408(%rsp), %rdi
callq 0x57f0
movl %eax, 0x30c(%rsp)
jmp 0x17c12
movl 0x30c(%rsp), %eax
cmpl $0x0, %eax
je 0x17f07
cmpq $0x8, 0x420(%rsp)
jle 0x17d2a
movq 0x418(%rsp), %rsi
addq $0x1, %rsi
leaq 0x5a93(%rip), %rdi      # 0x1d6d7
movl $0x6, %edx
callq 0x51e0
cmpl $0x0, %eax
jne 0x17d2a
movl $0x240, %edi            # imm = 0x240
callq 0x53e0
movq %rax, 0x300(%rsp)
jmp 0x17c6b
movq 0x300(%rsp), %rdi
movl 0x3cc(%rsp), %esi
callq 0x19110
jmp 0x17c81
movq 0x300(%rsp), %rax
movq %rax, 0x3f8(%rsp)
movq 0x3f8(%rsp), %rax
movq %rax, 0x2f0(%rsp)
movl 0x3cc(%rsp), %eax
movl %eax, 0x3bc(%rsp)
leaq 0x428(%rsp), %rdi
leaq 0x3bc(%rsp), %rsi
callq 0x191c0
movq %rax, 0x2f8(%rsp)
jmp 0x17cce
movq 0x2f8(%rsp), %rax
movq 0x2f0(%rsp), %rcx
movq %rcx, (%rax)
jmp 0x17f05
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x460(%rsp)
movl %eax, 0x45c(%rsp)
jmp 0x19039
movq 0x300(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x460(%rsp)
movl %eax, 0x45c(%rsp)
movl $0x240, %esi            # imm = 0x240
callq 0x5400
jmp 0x19039
cmpq $0x8, 0x420(%rsp)
jle 0x17e19
movq 0x418(%rsp), %rsi
addq $0x1, %rsi
leaq 0x5acf(%rip), %rdi      # 0x1d81b
movl $0x6, %edx
callq 0x51e0
cmpl $0x0, %eax
jne 0x17e19
movl $0x358, %edi            # imm = 0x358
callq 0x53e0
movq %rax, 0x2e8(%rsp)
jmp 0x17d73
movq 0x2e8(%rsp), %rdi
movl 0x3cc(%rsp), %esi
callq 0x192b0
jmp 0x17d89
movq 0x2e8(%rsp), %rax
movq %rax, 0x3f0(%rsp)
movq 0x3f0(%rsp), %rax
movq %rax, 0x2d8(%rsp)
movl 0x3cc(%rsp), %eax
movl %eax, 0x3b8(%rsp)
leaq 0x428(%rsp), %rdi
leaq 0x3b8(%rsp), %rsi
callq 0x191c0
movq %rax, 0x2e0(%rsp)
jmp 0x17dd6
movq 0x2e0(%rsp), %rax
movq 0x2d8(%rsp), %rcx
movq %rcx, (%rax)
jmp 0x17f03
movq 0x2e8(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x460(%rsp)
movl %eax, 0x45c(%rsp)
movl $0x358, %esi            # imm = 0x358
callq 0x5400
jmp 0x19039
cmpq $0x8, 0x420(%rsp)
jle 0x17f01
movq 0x418(%rsp), %rsi
leaq 0x5395(%rip), %rdi      # 0x1d1cc
movl $0x8, %edx
callq 0x51e0
cmpl $0x0, %eax
jne 0x17f01
movl $0x1e8, %edi            # imm = 0x1E8
callq 0x53e0
movq %rax, 0x2d0(%rsp)
jmp 0x17e5e
movq 0x2d0(%rsp), %rdi
movl 0x3cc(%rsp), %esi
callq 0x19330
jmp 0x17e74
movq 0x2d0(%rsp), %rax
movq %rax, 0x3e0(%rsp)
movq 0x3e0(%rsp), %rax
movq %rax, 0x2c0(%rsp)
movl 0x3cc(%rsp), %eax
movl %eax, 0x3b4(%rsp)
leaq 0x428(%rsp), %rdi
leaq 0x3b4(%rsp), %rsi
callq 0x191c0
movq %rax, 0x2c8(%rsp)
jmp 0x17ec1
movq 0x2c8(%rsp), %rax
movq 0x2c0(%rsp), %rcx
movq %rcx, (%rax)
jmp 0x17f01
movq 0x2d0(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x460(%rsp)
movl %eax, 0x45c(%rsp)
movl $0x1e8, %esi            # imm = 0x1E8
callq 0x5400
jmp 0x19039
jmp 0x17f03
jmp 0x17f05
jmp 0x17f07
movl 0x3cc(%rsp), %eax
movl %eax, 0x3b0(%rsp)
leaq 0x428(%rsp), %rdi
leaq 0x3b0(%rsp), %rsi
callq 0x191c0
movq %rax, 0x2b8(%rsp)
jmp 0x17f34
movq 0x2b8(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x3c0(%rsp)
cmpq $0x0, 0x3c0(%rsp)
jne 0x17fa8
movq 0x10077(%rip), %rdi     # 0x27fd0
leaq 0x6a20(%rip), %rsi      # 0x1e980
callq 0x53d0
movq %rax, 0x2b0(%rsp)
jmp 0x17f6f
movq 0x2b0(%rsp), %rdi
movl 0x3cc(%rsp), %esi
callq 0x57a0
movq %rax, 0x2a8(%rsp)
jmp 0x17f8d
movq 0x2a8(%rsp), %rdi
movq 0x10024(%rip), %rsi     # 0x27fc0
callq 0x5430
jmp 0x17fa3
jmp 0x17b13
movq 0x3c0(%rsp), %rdi
movq (%rdi), %rax
movq 0x10(%rax), %rax
leaq 0x408(%rsp), %rsi
leaq 0x3a8(%rsp), %rdx
callq *%rax
movq %rax, 0x2a0(%rsp)
jmp 0x17fd3
movq 0x2a0(%rsp), %rax
cmpq $0x0, %rax
jne 0x17fe9
movb $0x0, 0x3df(%rsp)
jmp 0x17b13
cmpq $0x0, 0x3e0(%rsp)
jne 0x18044
movq 0xfff0(%rip), %rdi      # 0x27ff0
leaq 0x69a1(%rip), %rsi      # 0x1e9a8
callq 0x53d0
movq %rax, 0x298(%rsp)
jmp 0x18016
movq 0x298(%rsp), %rdi
movq 0xff9b(%rip), %rsi      # 0x27fc0
callq 0x5430
jmp 0x1802c
movb $0x0, 0x6a7(%rsp)
movl $0x1, 0x3a4(%rsp)
jmp 0x1900e
movq 0x3e0(%rsp), %rax
movq 0x1e0(%rax), %rax
cmpq 0x3d0(%rsp), %rax
je 0x1811d
movq 0xff88(%rip), %rdi      # 0x27ff0
leaq 0x6973(%rip), %rsi      # 0x1e9e2
callq 0x53d0
movq %rax, 0x290(%rsp)
jmp 0x1807e
movq 0x290(%rsp), %rdi
movq 0x3e0(%rsp), %rax
movq 0x1e0(%rax), %rsi
callq 0x50c0
movq %rax, 0x288(%rsp)
jmp 0x180a4
movq 0x288(%rsp), %rdi
leaq 0x6961(%rip), %rsi      # 0x1ea14
callq 0x53d0
movq %rax, 0x280(%rsp)
jmp 0x180c2
movq 0x280(%rsp), %rdi
movq 0x3d0(%rsp), %rsi
callq 0x50c0
movq %rax, 0x278(%rsp)
jmp 0x180e1
movq 0x278(%rsp), %rdi
leaq 0x688e(%rip), %rsi      # 0x1e97e
callq 0x53d0
movq %rax, 0x270(%rsp)
jmp 0x180ff
movq 0x270(%rsp), %rdi
movq 0xfeb2(%rip), %rsi      # 0x27fc0
callq 0x5430
jmp 0x18115
movb $0x0, 0x3df(%rsp)
movq 0x698(%rsp), %rdi
callq 0x5180
movq %rax, %rdi
callq 0x15d40
movq %rax, 0x268(%rsp)
jmp 0x1813c
movq 0x268(%rsp), %rax
movq %rax, 0x398(%rsp)
movq 0x3e0(%rsp), %rax
movq 0x1d8(%rax), %rax
cmpq 0x398(%rsp), %rax
je 0x18225
movq 0xfe80(%rip), %rdi      # 0x27ff0
leaq 0x68c6(%rip), %rsi      # 0x1ea3d
callq 0x53d0
movq %rax, 0x260(%rsp)
jmp 0x18186
movq 0x260(%rsp), %rdi
movq 0x3e0(%rsp), %rax
movq 0x1d8(%rax), %rsi
callq 0x5810
movq %rax, 0x258(%rsp)
jmp 0x181ac
movq 0x258(%rsp), %rdi
leaq 0x68a7(%rip), %rsi      # 0x1ea62
callq 0x53d0
movq %rax, 0x250(%rsp)
jmp 0x181ca
movq 0x250(%rsp), %rdi
movq 0x398(%rsp), %rsi
callq 0x5810
movq %rax, 0x248(%rsp)
jmp 0x181e9
movq 0x248(%rsp), %rdi
leaq 0x6786(%rip), %rsi      # 0x1e97e
callq 0x53d0
movq %rax, 0x240(%rsp)
jmp 0x18207
movq 0x240(%rsp), %rdi
movq 0xfdaa(%rip), %rsi      # 0x27fc0
callq 0x5430
jmp 0x1821d
movb $0x0, 0x3df(%rsp)
movq 0x3e0(%rsp), %rdi
addq $0x1a8, %rdi            # imm = 0x1A8
callq 0x6f00
movq %rax, 0x390(%rsp)
movq 0x3e0(%rsp), %rdi
addq $0x1a8, %rdi            # imm = 0x1A8
callq 0x6f50
movq %rax, 0x388(%rsp)
leaq 0x390(%rsp), %rdi
leaq 0x388(%rsp), %rsi
callq 0xc680
testb $0x1, %al
jne 0x18278
jmp 0x182ad
movq 0xfd71(%rip), %rdi      # 0x27ff0
leaq 0x6803(%rip), %rsi      # 0x1ea89
callq 0x53d0
movq %rax, 0x238(%rsp)
jmp 0x18295
movq 0x238(%rsp), %rdi
movq 0xfd1c(%rip), %rsi      # 0x27fc0
callq 0x5430
jmp 0x182ab
jmp 0x182ad
jmp 0x182af
movq 0x3e0(%rsp), %rdi
addq $0x1a8, %rdi            # imm = 0x1A8
callq 0x6f50
movq %rax, 0x380(%rsp)
leaq 0x390(%rsp), %rdi
leaq 0x380(%rsp), %rsi
callq 0x6f30
testb $0x1, %al
jne 0x182e9
jmp 0x18fe4
leaq 0x390(%rsp), %rdi
movq %rdi, 0x228(%rsp)
callq 0x6f80
movq 0x228(%rsp), %rdi
movq 0x8(%rax), %rax
movq %rax, 0x378(%rsp)
callq 0x6f80
movq 0x228(%rsp), %rdi
movl (%rax), %eax
movl %eax, 0x374(%rsp)
xorl %esi, %esi
callq 0x6fa0
movq %rax, 0x368(%rsp)
leaq 0x428(%rsp), %rdi
leaq 0x374(%rsp), %rsi
callq 0x19390
movq %rax, 0x230(%rsp)
jmp 0x18356
movq 0x230(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x360(%rsp)
cmpq $0x0, 0x360(%rsp)
jne 0x183ca
movq 0xfc75(%rip), %rdi      # 0x27ff0
leaq 0x672d(%rip), %rsi      # 0x1eaaf
callq 0x53d0
movq %rax, 0x220(%rsp)
jmp 0x18391
movq 0x220(%rsp), %rdi
movl 0x374(%rsp), %esi
callq 0x5560
movq %rax, 0x218(%rsp)
jmp 0x183af
movq 0x218(%rsp), %rdi
movq 0xfc02(%rip), %rsi      # 0x27fc0
callq 0x5430
jmp 0x183c5
jmp 0x182af
movq 0x378(%rsp), %rdi
callq 0xa590
cmpq $0x0, %rax
jne 0x184ad
movq 0xfc08(%rip), %rdi      # 0x27ff0
leaq 0x66e1(%rip), %rsi      # 0x1ead0
callq 0x53d0
movq %rax, 0x210(%rsp)
jmp 0x183fe
movq 0x360(%rsp), %rdi
movq (%rdi), %rax
movq 0x20(%rax), %rax
callq *%rax
movq %rax, 0x208(%rsp)
jmp 0x18419
movq 0x208(%rsp), %rsi
movq 0x210(%rsp), %rdi
callq 0x53d0
movq %rax, 0x200(%rsp)
jmp 0x18438
movq 0x200(%rsp), %rdi
leaq 0x5c51(%rip), %rsi      # 0x1e098
callq 0x53d0
movq %rax, 0x1f8(%rsp)
jmp 0x18456
movq 0x1f8(%rsp), %rdi
movl 0x374(%rsp), %esi
callq 0x5560
movq %rax, 0x1f0(%rsp)
jmp 0x18474
movq 0x1f0(%rsp), %rdi
leaq 0x6657(%rip), %rsi      # 0x1eada
callq 0x53d0
movq %rax, 0x1e8(%rsp)
jmp 0x18492
movq 0x1e8(%rsp), %rdi
movq 0xfb1f(%rip), %rsi      # 0x27fc0
callq 0x5430
jmp 0x184a8
jmp 0x182af
movq 0x360(%rsp), %rdi
movq (%rdi), %rax
movq 0x20(%rax), %rax
callq *%rax
movq %rax, 0x1e0(%rsp)
jmp 0x184c8
movq 0x1e0(%rsp), %rsi
movq 0xfaf9(%rip), %rdi      # 0x27fd0
callq 0x53d0
movq %rax, 0x1d8(%rsp)
jmp 0x184e6
movq 0x1d8(%rsp), %rdi
leaq 0x5ba3(%rip), %rsi      # 0x1e098
callq 0x53d0
movq %rax, 0x1d0(%rsp)
jmp 0x18504
movq 0x1d0(%rsp), %rdi
movl 0x374(%rsp), %esi
callq 0x5560
movq %rax, 0x1c8(%rsp)
jmp 0x18522
movq 0x1c8(%rsp), %rdi
leaq 0x65c1(%rip), %rsi      # 0x1eaf2
callq 0x53d0
movq %rax, 0x1c0(%rsp)
jmp 0x18540
movq 0x378(%rsp), %rdi
callq 0xa590
movq 0x1c0(%rsp), %rdi
movq %rax, %rsi
callq 0x50c0
movq %rax, 0x1b8(%rsp)
jmp 0x18567
movq 0x1b8(%rsp), %rdi
leaq 0x6588(%rip), %rsi      # 0x1eafe
callq 0x53d0
movq %rax, 0x1b0(%rsp)
jmp 0x18585
movq 0x1b0(%rsp), %rdi
movq 0xfa2c(%rip), %rsi      # 0x27fc0
callq 0x5430
jmp 0x1859b
movb $0x1, 0x35f(%rsp)
movl $0x0, 0x358(%rsp)
movl 0x358(%rsp), %eax
movq %rax, 0x1a8(%rsp)
movq 0x378(%rsp), %rdi
callq 0xa590
movq %rax, %rcx
movq 0x1a8(%rsp), %rax
cmpq %rcx, %rax
jae 0x18e96
movq 0x378(%rsp), %rdi
movl 0x358(%rsp), %eax
movl %eax, %esi
callq 0x19480
movq %rax, 0x1a0(%rsp)
jmp 0x185fe
movq 0x1a0(%rsp), %rax
movq %rax, 0x350(%rsp)
movq 0x350(%rsp), %rax
cmpq $0x7fffffff, (%rax)     # imm = 0x7FFFFFFF
jle 0x18657
movq 0xf9ca(%rip), %rdi      # 0x27ff0
leaq 0x64dd(%rip), %rsi      # 0x1eb0a
callq 0x53d0
movq %rax, 0x198(%rsp)
jmp 0x1863c
movq 0x198(%rsp), %rdi
movq 0xf975(%rip), %rsi      # 0x27fc0
callq 0x5430
jmp 0x18652
jmp 0x18e96
movq 0x350(%rsp), %rax
movq (%rax), %rax
cmpq 0x398(%rsp), %rax
jle 0x1872c
movb $0x0, 0x35f(%rsp)
movq 0xf971(%rip), %rdi      # 0x27ff0
leaq 0x64bb(%rip), %rsi      # 0x1eb41
callq 0x53d0
movq %rax, 0x190(%rsp)
jmp 0x18695
movq 0x190(%rsp), %rdi
movl 0x358(%rsp), %esi
callq 0x5560
movq %rax, 0x188(%rsp)
jmp 0x186b3
movq 0x188(%rsp), %rdi
leaq 0x648f(%rip), %rsi      # 0x1eb51
callq 0x53d0
movq %rax, 0x180(%rsp)
jmp 0x186d1
movq 0x180(%rsp), %rdi
movq 0x350(%rsp), %rax
movq (%rax), %rsi
callq 0x5810
movq %rax, 0x178(%rsp)
jmp 0x186f3
movq 0x178(%rsp), %rdi
leaq 0x645b(%rip), %rsi      # 0x1eb5d
callq 0x53d0
movq %rax, 0x170(%rsp)
jmp 0x18711
movq 0x170(%rsp), %rdi
movq 0xf8a0(%rip), %rsi      # 0x27fc0
callq 0x5430
jmp 0x18727
jmp 0x18e96
leaq 0x470(%rsp), %rdi
callq 0x51d0
jmp 0x1873b
movq 0x490(%rsp), %rax
movq -0x18(%rax), %rax
leaq 0x490(%rsp,%rax), %rdi
callq 0x5850
movb %al, 0x16f(%rsp)
jmp 0x1875d
movb 0x16f(%rsp), %al
testb $0x1, %al
jne 0x1876a
jmp 0x187e3
leaq 0x490(%rsp), %rdi
callq 0x50a0
jmp 0x18779
movq 0x490(%rsp), %rax
movq -0x18(%rax), %rax
leaq 0x490(%rsp,%rax), %rdi
xorl %esi, %esi
callq 0x5770
jmp 0x18796
movq 0x698(%rsp), %rdi
callq 0x5180
movq %rax, 0x160(%rsp)
movl $0x8, %edi
movl $0x4, %esi
callq 0xe9f0
movl %eax, 0x168(%rsp)
jmp 0x187c3
movl 0x168(%rsp), %edx
movq 0x160(%rsp), %rsi
leaq 0x490(%rsp), %rdi
callq 0x5270
jmp 0x187e1
jmp 0x187e3
movq 0x350(%rsp), %rax
movq (%rax), %rsi
leaq 0x340(%rsp), %rdi
callq 0xec90
jmp 0x187fd
movq 0x340(%rsp), %rsi
movq 0x348(%rsp), %rdx
leaq 0x490(%rsp), %rdi
callq 0x5530
jmp 0x1881c
movq 0x490(%rsp), %rax
movq -0x18(%rax), %rax
leaq 0x490(%rsp,%rax), %rdi
callq 0x5780
movb %al, 0x15f(%rsp)
jmp 0x1883e
movb 0x15f(%rsp), %al
testb $0x1, %al
jne 0x188b8
jmp 0x1884b
movq 0xf79e(%rip), %rdi      # 0x27ff0
leaq 0x6318(%rip), %rsi      # 0x1eb71
callq 0x53d0
movq %rax, 0x150(%rsp)
jmp 0x18868
movq 0x150(%rsp), %rdi
movq 0x350(%rsp), %rax
movq (%rax), %rsi
callq 0x5810
movq %rax, 0x148(%rsp)
jmp 0x1888a
movq 0x148(%rsp), %rdi
movq 0xf727(%rip), %rsi      # 0x27fc0
callq 0x5430
jmp 0x188a0
movb $0x0, 0x6a7(%rsp)
movl $0x1, 0x3a4(%rsp)
jmp 0x1900e
movq 0x360(%rsp), %rdi
movq (%rdi), %rax
movq 0x18(%rax), %rax
callq *%rax
jmp 0x188cb
movq $-0x1, 0x338(%rsp)
movq 0x350(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x330(%rsp)
movq $-0x1, 0x328(%rsp)
cmpq $-0x1, 0x338(%rsp)
jne 0x18b97
movl $0x0, 0x324(%rsp)
leaq 0x470(%rsp), %rdi
leaq 0x408(%rsp), %rsi
leaq 0x490(%rsp), %rdx
leaq 0x400(%rsp), %rcx
callq 0x160c0
movl %eax, 0x144(%rsp)
jmp 0x1893e
movl 0x144(%rsp), %eax
movl %eax, 0x324(%rsp)
cmpl $0x0, %eax
je 0x18aa6
cmpl $-0x1, 0x324(%rsp)
jne 0x189c9
movq 0xf68a(%rip), %rdi      # 0x27ff0
leaq 0x6231(%rip), %rsi      # 0x1eb9e
callq 0x53d0
movq %rax, 0x138(%rsp)
jmp 0x1897c
movq 0x138(%rsp), %rdi
movq 0x330(%rsp), %rsi
callq 0x5810
movq %rax, 0x130(%rsp)
jmp 0x1899b
movq 0x130(%rsp), %rdi
movq 0xf616(%rip), %rsi      # 0x27fc0
callq 0x5430
jmp 0x189b1
movb $0x0, 0x6a7(%rsp)
movl $0x1, 0x3a4(%rsp)
jmp 0x1900e
cmpl $0x0, 0x324(%rsp)
jle 0x189d5
jmp 0x189f4
leaq 0x61e3(%rip), %rdi      # 0x1ebbf
leaq 0x5f64(%rip), %rsi      # 0x1e947
movl $0x2ab, %edx            # imm = 0x2AB
leaq 0x5f69(%rip), %rcx      # 0x1e958
callq 0x5280
movq 0xf5f5(%rip), %rdi      # 0x27ff0
leaq 0x61c6(%rip), %rsi      # 0x1ebc8
callq 0x53d0
movq %rax, 0x128(%rsp)
jmp 0x18a11
movq 0x128(%rsp), %rdi
movq 0x330(%rsp), %rsi
callq 0x5810
movq %rax, 0x120(%rsp)
jmp 0x18a30
movq 0x120(%rsp), %rdi
leaq 0x61aa(%rip), %rsi      # 0x1ebe9
callq 0x53d0
movq %rax, 0x118(%rsp)
jmp 0x18a4e
movq 0x118(%rsp), %rdi
movq 0x330(%rsp), %rsi
movslq 0x324(%rsp), %rax
addq %rax, %rsi
callq 0x5810
movq %rax, 0x110(%rsp)
jmp 0x18a78
movq 0x110(%rsp), %rdi
movq 0xf539(%rip), %rsi      # 0x27fc0
callq 0x5430
jmp 0x18a8e
movb $0x0, 0x6a7(%rsp)
movl $0x1, 0x3a4(%rsp)
jmp 0x1900e
movq 0x410(%rsp), %rcx
movq 0x420(%rsp), %rax
addq %rax, %rcx
movq 0x330(%rsp), %rax
addq %rcx, %rax
movq %rax, 0x330(%rsp)
leaq 0x408(%rsp), %rdi
callq 0x5350
movl %eax, 0x10c(%rsp)
jmp 0x18ae2
movl 0x10c(%rsp), %eax
movq 0x360(%rsp), %rcx
cmpl 0x8(%rcx), %eax
je 0x18afb
jmp 0x188f6
movq 0x360(%rsp), %rdi
movq (%rdi), %rax
movq 0x10(%rax), %rax
leaq 0x408(%rsp), %rsi
leaq 0x328(%rsp), %rdx
callq *%rax
movq %rax, 0x100(%rsp)
jmp 0x18b26
movq 0x100(%rsp), %rax
movq %rax, 0x338(%rsp)
movq 0x360(%rsp), %rcx
movb $0x1, %al
cmpq 0x3f0(%rsp), %rcx
movb %al, 0xff(%rsp)
jne 0x18b64
cmpq $-0x1, 0x338(%rsp)
setne %al
movb %al, 0xff(%rsp)
movb 0xff(%rsp), %al
testb $0x1, %al
jne 0x18b71
jmp 0x18b73
jmp 0x18b92
leaq 0x60a1(%rip), %rdi      # 0x1ec1b
leaq 0x5dc6(%rip), %rsi      # 0x1e947
movl $0x2bb, %edx            # imm = 0x2BB
leaq 0x5dcb(%rip), %rcx      # 0x1e958
callq 0x5280
jmp 0x188f6
movq 0x360(%rsp), %rax
cmpq 0x3f8(%rsp), %rax
jne 0x18cde
movq 0x350(%rsp), %rax
movq 0x8(%rax), %rax
cmpq 0x338(%rsp), %rax
je 0x18cde
movq 0xf422(%rip), %rdi      # 0x27ff0
leaq 0x606b(%rip), %rsi      # 0x1ec40
callq 0x53d0
movq %rax, 0xf0(%rsp)
jmp 0x18be4
movq 0xf0(%rsp), %rdi
movl 0x358(%rsp), %esi
callq 0x5560
movq %rax, 0xe8(%rsp)
jmp 0x18c02
movq 0xe8(%rsp), %rdi
leaq 0x5a9f(%rip), %rsi      # 0x1e6b0
callq 0x53d0
movq %rax, 0xe0(%rsp)
jmp 0x18c20
movq 0xe0(%rsp), %rdi
movq 0x350(%rsp), %rax
movq (%rax), %rsi
callq 0x5810
movq %rax, 0xd8(%rsp)
jmp 0x18c42
movq 0xd8(%rsp), %rdi
leaq 0x6006(%rip), %rsi      # 0x1ec57
callq 0x53d0
movq %rax, 0xd0(%rsp)
jmp 0x18c60
movq 0xd0(%rsp), %rdi
movq 0x350(%rsp), %rax
movq 0x8(%rax), %rsi
callq 0x5810
movq %rax, 0xc8(%rsp)
jmp 0x18c83
movq 0xc8(%rsp), %rdi
leaq 0x5fdd(%rip), %rsi      # 0x1ec6f
callq 0x53d0
movq %rax, 0xc0(%rsp)
jmp 0x18ca1
movq 0xc0(%rsp), %rdi
movq 0x338(%rsp), %rsi
callq 0x5810
movq %rax, 0xb8(%rsp)
jmp 0x18cc0
movq 0xb8(%rsp), %rdi
movq 0xf2f1(%rip), %rsi      # 0x27fc0
callq 0x5430
jmp 0x18cd6
movb $0x0, 0x35f(%rsp)
movq 0x360(%rsp), %rax
cmpq 0x3f0(%rsp), %rax
jne 0x18e7e
movq 0x350(%rsp), %rax
movq 0x8(%rax), %rax
cmpq 0x338(%rsp), %rax
jl 0x18d24
movq 0x350(%rsp), %rax
movq 0x8(%rax), %rax
cmpq 0x328(%rsp), %rax
jle 0x18e7e
movq 0xf2c5(%rip), %rdi      # 0x27ff0
leaq 0x5f4d(%rip), %rsi      # 0x1ec7f
callq 0x53d0
movq %rax, 0xb0(%rsp)
jmp 0x18d41
movq 0xb0(%rsp), %rdi
movl 0x358(%rsp), %esi
callq 0x5560
movq %rax, 0xa8(%rsp)
jmp 0x18d5f
movq 0xa8(%rsp), %rdi
leaq 0x5942(%rip), %rsi      # 0x1e6b0
callq 0x53d0
movq %rax, 0xa0(%rsp)
jmp 0x18d7d
movq 0xa0(%rsp), %rdi
movq 0x350(%rsp), %rax
movq (%rax), %rsi
callq 0x5810
movq %rax, 0x98(%rsp)
jmp 0x18d9f
movq 0x98(%rsp), %rdi
leaq 0x5ea9(%rip), %rsi      # 0x1ec57
callq 0x53d0
movq %rax, 0x90(%rsp)
jmp 0x18dbd
movq 0x90(%rsp), %rdi
movq 0x350(%rsp), %rax
movq 0x8(%rax), %rsi
callq 0x5810
movq %rax, 0x88(%rsp)
jmp 0x18de0
movq 0x88(%rsp), %rdi
leaq 0x5ea7(%rip), %rsi      # 0x1ec96
callq 0x53d0
movq %rax, 0x80(%rsp)
jmp 0x18dfe
movq 0x80(%rsp), %rdi
movq 0x338(%rsp), %rsi
callq 0x5810
movq %rax, 0x78(%rsp)
jmp 0x18e1a
movq 0x78(%rsp), %rdi
leaq 0x529a(%rip), %rsi      # 0x1e0c0
callq 0x53d0
movq %rax, 0x70(%rsp)
jmp 0x18e32
movq 0x70(%rsp), %rdi
movq 0x328(%rsp), %rsi
callq 0x5810
movq %rax, 0x68(%rsp)
jmp 0x18e4b
movq 0x68(%rsp), %rdi
leaq 0x4334(%rip), %rsi      # 0x1d18b
callq 0x53d0
movq %rax, 0x60(%rsp)
jmp 0x18e63
movq 0x60(%rsp), %rdi
movq 0xf151(%rip), %rsi      # 0x27fc0
callq 0x5430
jmp 0x18e76
movb $0x0, 0x35f(%rsp)
jmp 0x18e80
movl 0x358(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x358(%rsp)
jmp 0x185ae
testb $0x1, 0x35f(%rsp)
je 0x18f34
movq 0x360(%rsp), %rdi
movq (%rdi), %rax
movq 0x20(%rax), %rax
callq *%rax
movq %rax, 0x58(%rsp)
jmp 0x18ebc
movq 0x58(%rsp), %rsi
movq 0xf108(%rip), %rdi      # 0x27fd0
callq 0x53d0
movq %rax, 0x50(%rsp)
jmp 0x18ed4
movq 0x50(%rsp), %rdi
leaq 0x51b8(%rip), %rsi      # 0x1e098
callq 0x53d0
movq %rax, 0x48(%rsp)
jmp 0x18eec
movq 0x48(%rsp), %rdi
movl 0x374(%rsp), %esi
callq 0x5560
movq %rax, 0x40(%rsp)
jmp 0x18f04
movq 0x40(%rsp), %rdi
leaq 0x5da5(%rip), %rsi      # 0x1ecb5
callq 0x53d0
movq %rax, 0x38(%rsp)
jmp 0x18f1c
movq 0x38(%rsp), %rdi
movq 0xf098(%rip), %rsi      # 0x27fc0
callq 0x5430
jmp 0x18f2f
jmp 0x18fdf
movq 0xf095(%rip), %rdi      # 0x27fd0
leaq 0x5d87(%rip), %rsi      # 0x1ecc9
callq 0x53d0
movq %rax, 0x30(%rsp)
jmp 0x18f4e
movq 0x360(%rsp), %rdi
movq (%rdi), %rax
movq 0x20(%rax), %rax
callq *%rax
movq %rax, 0x28(%rsp)
jmp 0x18f66
movq 0x28(%rsp), %rsi
movq 0x30(%rsp), %rdi
callq 0x53d0
movq %rax, 0x20(%rsp)
jmp 0x18f7c
movq 0x20(%rsp), %rdi
leaq 0x5110(%rip), %rsi      # 0x1e098
callq 0x53d0
movq %rax, 0x18(%rsp)
jmp 0x18f94
movq 0x18(%rsp), %rdi
movl 0x374(%rsp), %esi
callq 0x5560
movq %rax, 0x10(%rsp)
jmp 0x18fac
movq 0x10(%rsp), %rdi
leaq 0x5d18(%rip), %rsi      # 0x1ecd0
callq 0x53d0
movq %rax, 0x8(%rsp)
jmp 0x18fc4
movq 0x8(%rsp), %rdi
movq 0xeff0(%rip), %rsi      # 0x27fc0
callq 0x5430
jmp 0x18fd7
movb $0x0, 0x3df(%rsp)
jmp 0x182af
leaq 0x470(%rsp), %rdi
callq 0x58c0
jmp 0x18ff3
movb 0x3df(%rsp), %al
andb $0x1, %al
movb %al, 0x6a7(%rsp)
movl $0x1, 0x3a4(%rsp)
leaq 0x428(%rsp), %rdi
callq 0x194c0
leaq 0x490(%rsp), %rdi
callq 0x50e0
movb 0x6a7(%rsp), %al
andb $0x1, %al
addq $0x6a8, %rsp            # imm = 0x6A8
retq
leaq 0x428(%rsp), %rdi
callq 0x194c0
leaq 0x490(%rsp), %rdi
callq 0x50e0
movq 0x460(%rsp), %rdi
callq 0x57d0