// File: 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
movq %rsp, %rbp
subq $0x170, %rsp            # imm = 0x170
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x148(%rbp)
leaq -0x4c(%rbp), %rdi
callq 0x8170
movq -0x148(%rbp), %rsi
leaq -0x70(%rbp), %rdi
callq 0x9f40
jmp 0x47b5
jmp 0x47b7
leaq -0x70(%rbp), %rdi
callq 0xa0c0
movb %al, -0x149(%rbp)
jmp 0x47c8
movb -0x149(%rbp), %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x480d
leaq -0x70(%rbp), %rdi
callq 0x4fc0
jmp 0x48b5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
jmp 0x4dc7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0x70(%rbp), %rdi
callq 0x4fc0
jmp 0x4dc7
leaq -0x4c(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0x81c0
jmp 0x481c
leaq -0x4c(%rbp), %rdi
callq 0x8320
movl %eax, -0x150(%rbp)
jmp 0x482d
movl -0x150(%rbp), %eax
movl %eax, -0x80(%rbp)
movl -0x80(%rbp), %eax
movl %eax, -0x154(%rbp)
testl %eax, %eax
je 0x485f
jmp 0x4845
movl -0x154(%rbp), %eax
subl $0x1, %eax
je 0x487a
jmp 0x4852
movl -0x154(%rbp), %eax
subl $0x2, %eax
je 0x4861
jmp 0x48a3
jmp 0x48a3
movq -0x148(%rbp), %rax
movq 0x25c0(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x25c0(%rax)
movq -0x148(%rbp), %rax
movq 0x25b8(%rax), %rcx
incq %rcx
movq %rcx, 0x25b8(%rax)
leaq -0x4c(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0x86d0
jmp 0x48a1
jmp 0x48a3
jmp 0x48a5
leaq -0x70(%rbp), %rdi
callq 0xa050
jmp 0x48b0
jmp 0x47b7
leaq -0xc0(%rbp), %rdi
callq 0x93b0
jmp 0x48c3
movq -0x148(%rbp), %rsi
leaq -0xe0(%rbp), %rdi
callq 0xa2a0
jmp 0x48d8
jmp 0x48da
leaq -0xe0(%rbp), %rdi
callq 0xa450
movb %al, -0x155(%rbp)
jmp 0x48ee
movb -0x155(%rbp), %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x4939
leaq -0xe0(%rbp), %rdi
callq 0x4fe0
jmp 0x49e1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
jmp 0x4dbb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0xe0(%rbp), %rdi
callq 0x4fe0
jmp 0x4dbb
leaq -0xc0(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
callq 0x9400
jmp 0x494e
leaq -0xc0(%rbp), %rdi
callq 0x9560
movl %eax, -0x15c(%rbp)
jmp 0x4962
movl -0x15c(%rbp), %eax
movl %eax, -0xe4(%rbp)
movl -0xe4(%rbp), %eax
movl %eax, -0x160(%rbp)
testl %eax, %eax
je 0x499a
jmp 0x4980
movl -0x160(%rbp), %eax
subl $0x1, %eax
je 0x499c
jmp 0x498d
movl -0x160(%rbp), %eax
subl $0x2, %eax
je 0x49b3
jmp 0x49cc
jmp 0x49cc
leaq -0xc0(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
callq 0x9920
jmp 0x49b1
jmp 0x49cc
movq -0x148(%rbp), %rax
movq 0x25c8(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x25c8(%rax)
jmp 0x49ce
leaq -0xe0(%rbp), %rdi
callq 0xa3b0
jmp 0x49dc
jmp 0x48da
movq $0x0, -0xf8(%rbp)
cmpq $0x7, -0xf8(%rbp)
jae 0x4a19
movq -0xf8(%rbp), %rax
movb $0x0, -0xeb(%rbp,%rax)
movq -0xf8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xf8(%rbp)
jmp 0x49ec
movq $0x0, -0x100(%rbp)
cmpq $0x10, -0x100(%rbp)
jae 0x4d9d
movq -0x100(%rbp), %rdx
andq $0x1, %rdx
movl $0x4, %eax
movl $0x3, %ecx
cmpq $0x0, %rdx
cmovnel %ecx, %eax
cltq
movq %rax, -0x108(%rbp)
movq -0x100(%rbp), %rax
addq $0x80, %rax
movq %rax, -0x110(%rbp)
movq -0x100(%rbp), %rdx
andq $0x1, %rdx
xorl %eax, %eax
movl $0x4, %ecx
cmpq $0x0, %rdx
cmovnel %ecx, %eax
movl %eax, -0x114(%rbp)
movq -0x110(%rbp), %rax
andq $0x1, %rax
cmpq $0x0, %rax
jne 0x4b10
movq -0x148(%rbp), %rax
testb $0x1, 0x85(%rax)
jne 0x4b0e
movq -0x148(%rbp), %rax
movq -0x110(%rbp), %rcx
testb $0x1, 0x251f(%rax,%rcx)
je 0x4b0e
movq -0x148(%rbp), %rax
movq -0x110(%rbp), %rcx
movzbl 0x248f(%rax,%rcx), %ecx
andl $0xf0, %ecx
sarl $0x4, %ecx
movb %cl, 0x84(%rax)
movq -0x110(%rbp), %rcx
movzbl 0x248f(%rax,%rcx), %ecx
andl $0xf, %ecx
movb %cl, 0x86(%rax)
movb $0x1, 0x85(%rax)
movb $0x1, 0x87(%rax)
jmp 0x4b10
movq $0x0, -0x120(%rbp)
movq -0x120(%rbp), %rax
cmpq -0x108(%rbp), %rax
jae 0x4d84
movq -0x148(%rbp), %rax
movq %rax, %rcx
addq $0x8f, %rcx
movq -0x110(%rbp), %rdx
shlq $0x5, %rdx
addq %rdx, %rcx
movq -0x120(%rbp), %rdx
shlq $0x3, %rdx
addq %rdx, %rcx
movq %rcx, -0x128(%rbp)
addq $0x128f, %rax           # imm = 0x128F
movq -0x110(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq -0x120(%rbp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, -0x130(%rbp)
movq -0x130(%rbp), %rax
testb $0x1, (%rax)
jne 0x4b9d
jmp 0x4d6d
movq -0x148(%rbp), %rax
movq -0x128(%rbp), %rcx
movzbl (%rcx), %ecx
andl $0xf0, %ecx
sarl $0x4, %ecx
movb %cl, -0x131(%rbp)
movzbl -0x131(%rbp), %ecx
testb $0x1, 0x74(%rax,%rcx)
je 0x4be8
movslq -0x114(%rbp), %rax
addq -0x120(%rbp), %rax
testb $0x1, -0xeb(%rbp,%rax)
je 0x4be8
jmp 0x4d6d
movq $0x0, -0x140(%rbp)
movb $0x0, -0x132(%rbp)
movb $0x1, -0x133(%rbp)
cmpq $0x8, -0x140(%rbp)
jae 0x4c7c
movq -0x128(%rbp), %rax
movq -0x140(%rbp), %rcx
movzbl (%rax,%rcx), %ecx
andl $0xff, %ecx
movzbl -0x132(%rbp), %eax
xorl %ecx, %eax
movb %al, -0x132(%rbp)
xorl %eax, %eax
testb $0x1, -0x133(%rbp)
movb %al, -0x161(%rbp)
je 0x4c5a
movq -0x130(%rbp), %rax
movq -0x140(%rbp), %rcx
movb (%rax,%rcx), %al
movb %al, -0x161(%rbp)
movb -0x161(%rbp), %al
andb $0x1, %al
movb %al, -0x133(%rbp)
movq -0x140(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x140(%rbp)
jmp 0x4c01
testb $0x1, -0x133(%rbp)
je 0x4c91
movzbl -0x132(%rbp), %eax
cmpl $0x0, %eax
je 0x4c96
jmp 0x4d6d
movq -0x148(%rbp), %rax
movzbl -0x131(%rbp), %ecx
testb $0x1, 0x74(%rax,%rcx)
jne 0x4d1b
movq $0x0, -0x140(%rbp)
cmpq $0x7, -0x140(%rbp)
jae 0x4d08
movq -0x148(%rbp), %rax
movq -0x128(%rbp), %rcx
movq -0x140(%rbp), %rdx
movb (%rcx,%rdx), %dl
addq $0x4, %rax
movzbl -0x131(%rbp), %ecx
imulq $0x7, %rcx, %rcx
addq %rcx, %rax
movq -0x140(%rbp), %rcx
movb %dl, (%rax,%rcx)
movq -0x140(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x140(%rbp)
jmp 0x4cb6
movq -0x148(%rbp), %rax
movzbl -0x131(%rbp), %ecx
movb $0x1, 0x74(%rax,%rcx)
movslq -0x114(%rbp), %rax
addq -0x120(%rbp), %rax
testb $0x1, -0xeb(%rbp,%rax)
jne 0x4d6b
movq -0x148(%rbp), %rax
movb -0x131(%rbp), %dl
movslq -0x114(%rbp), %rcx
addq -0x120(%rbp), %rcx
movb %dl, 0x88(%rax,%rcx)
movslq -0x114(%rbp), %rax
addq -0x120(%rbp), %rax
movb $0x1, -0xeb(%rbp,%rax)
jmp 0x4d6d
movq -0x120(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x120(%rbp)
jmp 0x4b1b
jmp 0x4d86
movq -0x100(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x100(%rbp)
jmp 0x4a24
leaq -0xc0(%rbp), %rdi
callq 0x93f0
leaq -0x4c(%rbp), %rdi
callq 0x81b0
addq $0x170, %rsp            # imm = 0x170
popq %rbp
retq
leaq -0xc0(%rbp), %rdi
callq 0x93f0
leaq -0x4c(%rbp), %rdi
callq 0x81b0
movq -0x78(%rbp), %rdi
callq 0x21d0
nopl (%rax)