// File: /workspace/github_cpp_makefile_star2_O1/ke6jjj[P]r-dat/Track.cc
// Function: Track::Complete()
void
Track::Complete()
{
  ECC_C1 Vp;
    
  //
  // Iterate over each pair of blocks, correcting the C1 errors in each.
  //
  for (ECCFill_C1 c1_fill(*this); !c1_fill.End(); c1_fill.Next()) {
    //
    // Fill the error check vector.
    //
    Vp.Fill(c1_fill);
    
    //
    // Detect errors in this vector and correct them.
    //
    ECC_C1::Status ok = Vp.Correct();
    switch (ok) {
    case ECC_C1::NO_ERRORS:
      //
      // No errors. Nothing to be done.
      //
      break;
    case ECC_C1::UNCORRECTABLE:
      mC1UncorrectableErrors++;
    case ECC_C1::CORRECTED:
      //
      // There were errors, they were either corrected or the whole vector
      // has been marked bad. Put the corrected or invalidated data back into
      // the track.
      //
      mC1Errors++;
      Vp.Dump(c1_fill);
      break;
    }
  }

  //
  // Now iterate over each block 4-group to perform C2 error correction.
  //
  ECC_C2 Vq;

  for (ECCFill_C2 c2_fill(*this); !c2_fill.End(); c2_fill.Next()) {
    //
    // Fill the error check vector.
    //      
    Vq.Fill(c2_fill);

    //
    // Detect errors in this vector and correct them.
    //
    ECC_C2::Status c2ok = Vq.Correct();
    switch (c2ok) {
    case ECC_C2::NO_ERRORS:
      //
      // No errors. Nothing to be done.
      //
      break;
    case ECC_C2::CORRECTED:
      //
      // There were errors but they were corrected.
      // Put the corrected data back into the track.
      //
      Vq.Dump(c2_fill);
      break;
    case ECC_C2::UNCORRECTABLE:
      //
      // Slice was uncorrectable. Leave it as is. The next level of
      // error handling (interpolation for Audio, C3 for DDS) will have
      // to deal with it.
      //
      mC2UncorrectableErrors++;
      break;
    }
  }

  //
  // Error correction is complete. Now dather data from the sub-code blocks.
  //
  //
  // Now all the sub-code blocks have had as much error correction applied
  // as they ever will. Build the sub-code signature.
  //
  // Examine blocks 0x80-0x8f, the sub-code blocks, and build up a complete
  // list of the seven sub-code identifiers used in this track and the order
  // in which they are specified.
  //
  bool have_subcode_slot[7];
  for (size_t i = 0; i < 7; i++)
    have_subcode_slot[i] = false;
  
  for (size_t i = 0; i < 16; i++) {
    //
    // Odd-numbered blocks have three sub-codes. Even blocks have four.
    //
    size_t limit = (i & 1) ? 3 : 4;
    size_t block_number = 0x80 + i;
    int    slot_start = (i & 1) ? 4 : 0;

    //
    // Grab the ControlID and DataID from the first valid even-numbered
    // Subcode block.
    //
    if ((block_number & 1) == 0) {
      if (!mHaveControlID && mHeaderIsValid[block_number]) {
        mControlID = (mHeader[block_number] & 0xf0) >> 4;
        mDataID    = (mHeader[block_number] & 0x0f);
        mHaveControlID = true;
        mHaveDataID = true;
      }
    }
    
    //
    // Examine the individal sub-codes in this block.
    //
    for (size_t j = 0; j < limit; j++) {
      //
      // Point straight at the 8-byte item.
      //
      const uint8_t *item = &(mData[block_number][8*j]);
      const bool    *validity = &(mDataIsValid[block_number][8*j]);

      //
      // What's the sub-code id?
      //
      if (!validity[0])
        //
        // Sub-code id byte isn't even valid. Don't bother.
        //
        continue;

      uint8_t subcode_id = (item[0] & 0xf0) >> 4;

      //
      // Do we already have this sub-code?
      //
      if (mSubcodeIsValid[subcode_id] && have_subcode_slot[slot_start+j])
        //
        // Already have it. Skip it.
        //
        continue;

      //
      // Check the whole subcode item parity and make sure there
      // are no erasure symbols here.
      //
      uint8_t parity;
      bool valid;
      size_t k;
      for (k = 0, parity = 0, valid = true; k < 8; k++) {
        parity ^= item[k] & 0xff;
        valid = valid && validity[k];
      }

      if (!valid || parity != 0)
        //
        // Item parity or validity is bad.
        //
        continue;
    
      if (!mSubcodeIsValid[subcode_id]) {
        //
        // Copy the sub-code into its slot and mark it valid.
        //
        for (k = 0; k < 7; k++)
          mSubcode[subcode_id][k] = item[k];
    
        mSubcodeIsValid[subcode_id] = true;
      }
      
      if (!have_subcode_slot[slot_start+j]) {
        //
        // Copy the sub-code identifier into the subcode signature.
        //
        mSubcodeSignature[slot_start+j] = subcode_id;
        have_subcode_slot[slot_start+j] = true;
      }
    }
  }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xd8, %rsp
movq %rdi, %rbx
leaq 0x94(%rsp), %rdi
callq 0x52a8
leaq 0x50(%rsp), %rdi
movq %rbx, %rsi
callq 0x630c
leaq 0x50(%rsp), %r14
leaq 0x94(%rsp), %r15
movq %r14, %rdi
callq 0x63b0
testb %al, %al
jne 0x36b5
movq %r15, %rdi
movq %r14, %rsi
callq 0x52ac
movq %r15, %rdi
callq 0x535e
cmpl $0x1, %eax
je 0x3699
cmpl $0x2, %eax
jne 0x36ab
incq 0x25c0(%rbx)
incq 0x25b8(%rbx)
movq %r15, %rdi
movq %r14, %rsi
callq 0x5562
movq %r14, %rdi
callq 0x637c
jmp 0x3669
leaq 0x50(%rsp), %rdi
callq 0x5c8c
leaq 0x30(%rsp), %rdi
movq %rbx, %rsi
callq 0x641c
leaq 0x30(%rsp), %r14
leaq 0x50(%rsp), %r15
movq %r14, %rdi
callq 0x64d2
testb %al, %al
jne 0x371d
movq %r15, %rdi
movq %r14, %rsi
callq 0x5c90
movq %r15, %rdi
callq 0x5d42
cmpl $0x1, %eax
je 0x3708
cmpl $0x2, %eax
jne 0x3713
incq 0x25c8(%rbx)
jmp 0x3713
movq %r15, %rdi
movq %r14, %rsi
callq 0x5f36
movq %r14, %rdi
callq 0x6486
jmp 0x36d6
xorl %edx, %edx
movl %edx, 0x33(%rsp)
movl %edx, 0x30(%rsp)
leaq 0x8f(%rbx), %rax
movq %rax, 0x8(%rsp)
leaq 0x128f(%rbx), %rax
movq %rax, (%rsp)
leaq 0x228f(%rbx), %r13
leaq 0x108f(%rbx), %r12
leaq 0x4(%rbx), %rax
movq %rax, 0x28(%rsp)
movq %rdx, %r10
orq $0x80, %r10
testb $0x1, %dl
jne 0x37a1
cmpb $0x0, 0x85(%rbx)
jne 0x37a1
cmpb $0x1, 0x251f(%rbx,%r10)
jne 0x37a1
movb 0x248f(%rbx,%r10), %al
movl %eax, %ecx
shrb $0x4, %cl
movb %cl, 0x84(%rbx)
andb $0xf, %al
movb %al, 0x86(%rbx)
movb $0x1, %al
movb %al, 0x85(%rbx)
movb %al, 0x87(%rbx)
movq %rdx, 0x20(%rsp)
movl %edx, %eax
andl $0x1, %eax
movl $0x4, %r11d
subq %rax, %r11
shll $0x2, %eax
movl %eax, %r14d
shlq $0x5, %r10
movq 0x8(%rsp), %rax
leaq (%rax,%r10), %r15
addq (%rsp), %r10
movq %r12, 0x10(%rsp)
movq %r13, 0x18(%rsp)
xorl %ebp, %ebp
cmpb $0x1, (%r10,%rbp,8)
jne 0x3881
leaq (%r15,%rbp,8), %rax
movzbl (%rax), %r9d
shrl $0x4, %r9d
movb 0x74(%rbx,%r9), %cl
cmpb $0x1, %cl
jne 0x3803
leaq (%r14,%rbp), %rax
cmpb $0x0, 0x30(%rsp,%rax)
jne 0x3881
movb $0x1, %dl
xorl %r8d, %r8d
xorl %eax, %eax
movl %eax, %esi
testb $0x1, %dl
je 0x3818
movb (%r13,%r8), %dl
jmp 0x381a
xorl %edx, %edx
movb -0x1200(%r13,%r8), %dil
movl %edi, %eax
xorb %sil, %al
incq %r8
cmpq $0x8, %r8
jne 0x380a
cmpb %sil, %dil
sete %al
andb %al, %dl
cmpb $0x1, %dl
jne 0x3881
testb %cl, %cl
jne 0x3869
leaq (,%r9,8), %rcx
subq %r9, %rcx
addq 0x28(%rsp), %rcx
xorl %eax, %eax
movb (%r12,%rax), %dl
movb %dl, (%rcx,%rax)
incq %rax
cmpq $0x7, %rax
jne 0x3853
movb $0x1, 0x74(%rbx,%r9)
leaq (%r14,%rbp), %rax
cmpb $0x0, 0x30(%rsp,%rax)
jne 0x3881
movb %r9b, 0x88(%rbx,%rax)
movb $0x1, 0x30(%rsp,%rax)
incq %rbp
addq $0x8, %r13
addq $0x8, %r12
cmpq %r11, %rbp
jne 0x37d7
movq 0x20(%rsp), %rdx
incq %rdx
movq 0x18(%rsp), %r13
addq $0x20, %r13
movq 0x10(%rsp), %r12
addq $0x20, %r12
cmpq $0x10, %rdx
jne 0x3755
leaq 0x50(%rsp), %rdi
callq 0x5c8e
leaq 0x94(%rsp), %rdi
callq 0x52aa
addq $0xd8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x38ec
jmp 0x38fb
jmp 0x38fb
jmp 0x38ec
jmp 0x38fb
movq %rax, %rbx
leaq 0x50(%rsp), %rdi
callq 0x5c8e
jmp 0x38fe
movq %rax, %rbx
leaq 0x94(%rsp), %rdi
callq 0x52aa
movq %rbx, %rdi
callq 0x21d0
nop