// File: /workspace/github_cpp_makefile_star2_O2/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 $0xc8, %rsp
movq %rdi, %rbx
leaq 0x84(%rsp), %rdi
callq 0x5130
leaq 0x40(%rsp), %rdi
movq %rbx, %rsi
callq 0x60dc
leaq 0x40(%rsp), %r14
leaq 0x84(%rsp), %r15
movq %r14, %rdi
callq 0x617e
testb %al, %al
jne 0x351f
movq %r15, %rdi
movq %r14, %rsi
callq 0x5134
movq %r15, %rdi
callq 0x51ec
cmpl $0x1, %eax
je 0x3503
cmpl $0x2, %eax
jne 0x3515
incq 0x25c0(%rbx)
incq 0x25b8(%rbx)
movq %r15, %rdi
movq %r14, %rsi
callq 0x53b4
movq %r14, %rdi
callq 0x614a
jmp 0x34d3
leaq 0x40(%rsp), %rdi
callq 0x5a80
leaq 0x20(%rsp), %rdi
movq %rbx, %rsi
callq 0x61e8
leaq 0x20(%rsp), %r14
leaq 0x40(%rsp), %r15
movq %r14, %rdi
callq 0x6296
testb %al, %al
jne 0x3587
movq %r15, %rdi
movq %r14, %rsi
callq 0x5a84
movq %r15, %rdi
callq 0x5b3c
cmpl $0x1, %eax
je 0x3572
cmpl $0x2, %eax
jne 0x357d
incq 0x25c8(%rbx)
jmp 0x357d
movq %r15, %rdi
movq %r14, %rsi
callq 0x5d12
movq %r14, %rdi
callq 0x6250
jmp 0x3540
xorl %eax, %eax
cmpq $0x7, %rax
je 0x3599
movb $0x0, 0x20(%rsp,%rax)
incq %rax
jmp 0x3589
leaq 0x8f(%rbx), %rax
movq %rax, 0x8(%rsp)
leaq 0x128f(%rbx), %rax
movq %rax, (%rsp)
leaq 0x228f(%rbx), %rbp
leaq 0x4(%rbx), %rax
movq %rax, 0x18(%rsp)
leaq 0x108f(%rbx), %rdi
xorl %r8d, %r8d
cmpq $0x10, %r8
je 0x371b
movq %r8, %r11
orq $0x80, %r11
testb $0x1, %r8b
jne 0x3621
cmpb $0x0, 0x85(%rbx)
jne 0x3621
cmpb $0x1, 0x251f(%rbx,%r11)
jne 0x3621
movb 0x248f(%rbx,%r11), %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)
movl %r8d, %r14d
andl $0x1, %r14d
pushq $0x4
popq %r15
subq %r14, %r15
shll $0x2, %r14d
shlq $0x5, %r11
movq 0x8(%rsp), %rax
leaq (%rax,%r11), %r12
addq (%rsp), %r11
movq %rdi, %r13
movq %rbp, 0x10(%rsp)
xorl %r10d, %r10d
cmpq %r15, %r10
je 0x3706
cmpb $0x1, (%r11,%r10,8)
jne 0x36f6
leaq (%r12,%r10,8), %rax
movzbl (%rax), %r9d
shrl $0x4, %r9d
movb 0x74(%rbx,%r9), %al
cmpb $0x1, %al
jne 0x3683
leaq (%r10,%r14), %rcx
cmpb $0x0, 0x20(%rsp,%rcx)
jne 0x36f6
movb $0x1, %cl
xorl %esi, %esi
xorl %edx, %edx
cmpq $0x8, %rdx
je 0x36a9
testb $0x1, %cl
je 0x369a
movb (%rbp,%rdx), %cl
jmp 0x369c
xorl %ecx, %ecx
xorb -0x1200(%rbp,%rdx), %sil
incq %rdx
jmp 0x3689
testb %sil, %sil
sete %dl
andb %dl, %cl
cmpb $0x1, %cl
jne 0x36f6
testb %al, %al
jne 0x36de
imulq $0x7, %r9, %rax
addq 0x18(%rsp), %rax
xorl %ecx, %ecx
cmpq $0x7, %rcx
je 0x36d8
movb (%r13,%rcx), %dl
movb %dl, (%rax,%rcx)
incq %rcx
jmp 0x36c5
movb $0x1, 0x74(%rbx,%r9)
leaq (%r10,%r14), %rax
cmpb $0x0, 0x20(%rsp,%rax)
jne 0x36f6
movb %r9b, 0x88(%rbx,%rax)
movb $0x1, 0x20(%rsp,%rax)
incq %r10
addq $0x8, %rbp
addq $0x8, %r13
jmp 0x364f
incq %r8
movq 0x10(%rsp), %rbp
addq $0x20, %rbp
addq $0x20, %rdi
jmp 0x35ca
leaq 0x40(%rsp), %rdi
callq 0x5a82
leaq 0x84(%rsp), %rdi
callq 0x5132
addq $0xc8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x374e
jmp 0x375d
jmp 0x375d
jmp 0x374e
jmp 0x375d
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
callq 0x5a82
jmp 0x3760
movq %rax, %rbx
leaq 0x84(%rsp), %rdi
callq 0x5132
movq %rbx, %rdi
callq 0x21e0
nop