// File: ke6jjj[P]r-dat/BasicGroup.cc
// Function: BasicGroup::AddSubFrame(DDSGroup1 const&)
bool
BasicGroup::AddSubFrame(const DDSGroup1& frame)
{
  //
  // Make certain that this sub-frame belongs to this group.
  //
  if (frame.BasicGroupID() != mBasicGroupID) {
    printf("Attempt to add sub-frame to wrong basic group!\n");
    return false;
  }

  //
  // Don't dump sub-frame zero, if you ever encounter one.
  //
  if (frame.SubFrameID() == 0)
    return true;

  //
  // ECC frames get special treatment.
  //
  bool is_ecc = frame.IsECCFrame();
    
  //
  // Derive pointers into the appropriate place in out data to capture
  // this new frame.
  // 
  uint8_t *data_existing;
  bool *valid_existing;
  if (!is_ecc) {
    //
    // Normal data frame. Frames are numbered starting at 1 and are
    // about 5k in size.
    //
    size_t pos = DDSGroup1::kSize * (frame.SubFrameID() - 1);
    data_existing = &mData[pos];
    valid_existing = &mDataIsValid[pos];
  } else {
    //
    // ECC frames go into their own buffer.
    //
    data_existing = &mECCData[0];
    valid_existing = &mECCDataIsValid[0];
  }
  
  //
  // Get pointers to the frame data and validity buffer.
  //
  const DDSGroup1::DataArray& data = frame.Data();
  const DDSGroup1::ValidArray& valid = frame.Valid();
  
  //
  // Incorporate the frame's data as long as it is better than the existing
  // data.
  //
  for (size_t i = 0; i < DDSGroup1::kSize; i++) {
    if (valid[i] && !valid_existing[i]) {
      //
      // New valid data that replaces invalid data. Use it!
      //
      data_existing[i] = data[i];
      valid_existing[i] = true;
    } else if (valid[i] && valid_existing[i]) {
      //
      // We already have data at this spot. Check to make sure that the
      // update is the same.
      //
      if (data[i] != data_existing[i]) {
        //
        // Oh oh, mistmatch.
        //
        printf("Reread mismatch at Basic Group %d, SubGroup %d, offset %zd"
               ". Old/New = %02x/%02x. Keeping existing data.\n",
               frame.BasicGroupID(), frame.SubFrameID(), i, data_existing[i],
               data[i]);
      }
    } else if (!valid[i] && !valid_existing[i]) {
      //
      // Existing data is invalid and incoming data is also marked invalid,
      // but the incoming data likely has more information than the existing.
      // Sometimes entire blocks get marked invalid due to error detection
      // but a good deal of the block is actually correct. We have enough
      // storage space to represent the data invalidity yet retain the likely
      // correct data.
      //
      // Copy in the supposedly invalid data.
      //
      data_existing[i] = data[i];
      valid_existing[i] = valid[i];
    }
  }
  
  return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x58(%rbp)
movq -0x18(%rbp), %rdi
callq 0xaa10
movq -0x58(%rbp), %rcx
cmpl (%rcx), %eax
je 0xb370
leaq 0x4793(%rip), %rdi      # 0xfaf3
movb $0x0, %al
callq 0x2040
movb $0x0, -0x1(%rbp)
jmp 0xb556
movq -0x18(%rbp), %rdi
callq 0xaa70
movzbl %al, %eax
cmpl $0x0, %eax
jne 0xb38a
movb $0x1, -0x1(%rbp)
jmp 0xb556
movq -0x18(%rbp), %rdi
callq 0xaa50
andb $0x1, %al
movb %al, -0x19(%rbp)
testb $0x1, -0x19(%rbp)
jne 0xb3e0
movq -0x18(%rbp), %rdi
callq 0xaa70
movb %al, %cl
movq -0x58(%rbp), %rax
movzbl %cl, %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
imulq $0x167c, %rcx, %rcx     # imm = 0x167C
movq %rcx, -0x38(%rbp)
movq %rax, %rcx
addq $0x4, %rcx
addq -0x38(%rbp), %rcx
movq %rcx, -0x28(%rbp)
addq $0x1eeac, %rax          # imm = 0x1EEAC
addq -0x38(%rbp), %rax
movq %rax, -0x30(%rbp)
jmp 0xb3fc
movq -0x58(%rbp), %rax
movq %rax, %rcx
addq $0x3dd54, %rcx          # imm = 0x3DD54
movq %rcx, -0x28(%rbp)
addq $0x3f3d0, %rax          # imm = 0x3F3D0
movq %rax, -0x30(%rbp)
movq -0x18(%rbp), %rdi
callq 0xa9e0
movq %rax, -0x40(%rbp)
movq -0x18(%rbp), %rdi
callq 0xa9f0
movq %rax, -0x48(%rbp)
movq $0x0, -0x50(%rbp)
cmpq $0x167c, -0x50(%rbp)    # imm = 0x167C
jae 0xb552
movq -0x48(%rbp), %rax
movq -0x50(%rbp), %rcx
testb $0x1, (%rax,%rcx)
je 0xb46f
movq -0x30(%rbp), %rax
movq -0x50(%rbp), %rcx
testb $0x1, (%rax,%rcx)
jne 0xb46f
movq -0x40(%rbp), %rax
movq -0x50(%rbp), %rcx
movb (%rax,%rcx), %dl
movq -0x28(%rbp), %rax
movq -0x50(%rbp), %rcx
movb %dl, (%rax,%rcx)
movq -0x30(%rbp), %rax
movq -0x50(%rbp), %rcx
movb $0x1, (%rax,%rcx)
jmp 0xb53f
movq -0x48(%rbp), %rax
movq -0x50(%rbp), %rcx
testb $0x1, (%rax,%rcx)
je 0xb4f0
movq -0x30(%rbp), %rax
movq -0x50(%rbp), %rcx
testb $0x1, (%rax,%rcx)
je 0xb4f0
movq -0x40(%rbp), %rax
movq -0x50(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movq -0x28(%rbp), %rcx
movq -0x50(%rbp), %rdx
movzbl (%rcx,%rdx), %ecx
cmpl %ecx, %eax
je 0xb4ee
movq -0x18(%rbp), %rdi
callq 0xaa10
movl %eax, -0x5c(%rbp)
movq -0x18(%rbp), %rdi
callq 0xaa70
movl -0x5c(%rbp), %esi
movzbl %al, %edx
movq -0x50(%rbp), %rcx
movq -0x28(%rbp), %rax
movq -0x50(%rbp), %rdi
movzbl (%rax,%rdi), %r8d
movq -0x40(%rbp), %rax
movq -0x50(%rbp), %rdi
movzbl (%rax,%rdi), %r9d
leaq 0x463c(%rip), %rdi      # 0xfb23
movb $0x0, %al
callq 0x2040
jmp 0xb53d
movq -0x48(%rbp), %rax
movq -0x50(%rbp), %rcx
testb $0x1, (%rax,%rcx)
jne 0xb53b
movq -0x30(%rbp), %rax
movq -0x50(%rbp), %rcx
testb $0x1, (%rax,%rcx)
jne 0xb53b
movq -0x40(%rbp), %rax
movq -0x50(%rbp), %rcx
movb (%rax,%rcx), %dl
movq -0x28(%rbp), %rax
movq -0x50(%rbp), %rcx
movb %dl, (%rax,%rcx)
movq -0x48(%rbp), %rax
movq -0x50(%rbp), %rcx
movb (%rax,%rcx), %dl
movq -0x30(%rbp), %rax
movq -0x50(%rbp), %rcx
andb $0x1, %dl
movb %dl, (%rax,%rcx)
jmp 0xb53d
jmp 0xb53f
jmp 0xb541
movq -0x50(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x50(%rbp)
jmp 0xb41e
movb $0x1, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x60, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)