// File: tomfunkhouser[P]gaps/pkgs/R3Surfels/R3SurfelDatabase.cpp
// Function: gaps::R3SurfelDatabase::WriteSurfel(_IO_FILE*, gaps::R3Surfel*, int, int, unsigned int, unsigned int) const
int R3SurfelDatabase::
WriteSurfel(FILE *fp, R3Surfel *ptr, int count, int swap_endian, 
  unsigned int major_version, unsigned int minor_version) const
{
  // Swap endian
  if (swap_endian) {
    for (int i = 0; i < count; i++) {
      RNSwap4(ptr[i].position, 3);
      RNSwap2(ptr[i].normal, 3);
      RNSwap2(ptr[i].tangent, 3);
      RNSwap2(ptr[i].radius, 2);
      RNSwap2(&ptr[i].depth, 1);
      RNSwap2(&ptr[i].elevation, 1);
      RNSwap4(&ptr[i].timestamp, 1);
      RNSwap4(&ptr[i].identifier, 1);
      RNSwap4(&ptr[i].attribute, 1);
    }
  }

  // Clear surfel marks
  for (int i = 0; i < count; i++) ptr[i].SetMark(FALSE);

  // Write current version of surfel
  int status = 1;
  if ((major_version == current_major_version) && (minor_version == current_minor_version)) {
    int sofar = 0;
    while (sofar < count) {
      size_t n = fwrite(ptr, sizeof(R3Surfel), count - sofar, fp);
      if (n > 0) sofar += n;
      else { RNFail("Unable to write surfel to database file\n"); status = 0; }
    }
  }
  else {
    if (major_version == 5) {
      for (int i = 0; i < count; i++) {
        unsigned int encoded_elevation = 0;
        if (ptr[i].Elevation() != 0) encoded_elevation = 400 * ptr[i].Elevation() + 32768;
        RNUInt32 attribute = (ptr[i].Attribute() & 0x0000FFFF) | (encoded_elevation << 16);
        fwrite(ptr[i].position, sizeof(RNScalar32), 3, fp);
        fwrite(&ptr[i].timestamp, sizeof(RNScalar32), 1, fp);
        fwrite(ptr[i].normal, sizeof(RNInt16), 3, fp);
        fwrite(ptr[i].tangent, sizeof(RNInt16), 3, fp);
        fwrite(ptr[i].radius, sizeof(RNInt16), 2, fp);
        fwrite(&ptr[i].identifier, sizeof(RNUInt32), 1, fp);
        fwrite(&attribute, sizeof(RNUInt32), 1, fp);
        fwrite(ptr[i].color, sizeof(RNUChar8), 3, fp);
        fwrite(&ptr[i].flags, sizeof(RNUChar8), 1, fp);
      }
    }
    else if (major_version == 4) {
      for (int i = 0; i < count; i++) {
        fwrite(ptr[i].position, sizeof(RNScalar32), 3, fp);
        fwrite(&ptr[i].timestamp, sizeof(RNScalar32), 1, fp);
        fwrite(ptr[i].normal, sizeof(RNInt16), 3, fp);
        fwrite(ptr[i].tangent, sizeof(RNInt16), 3, fp);
        fwrite(ptr[i].radius, sizeof(RNInt16), 2, fp);
        fwrite(&ptr[i].identifier, sizeof(RNUInt32), 1, fp);
        fwrite(ptr[i].color, sizeof(RNUChar8), 3, fp);
        fwrite(&ptr[i].flags, sizeof(RNUChar8), 1, fp);
      }
    }
    else if (major_version == 3) {
      for (int i = 0; i < count; i++) {
        fwrite(ptr[i].position, sizeof(RNScalar32), 3, fp);
        fwrite(ptr[i].normal, sizeof(RNInt16), 3, fp);
        fwrite(&ptr[i].radius[0], sizeof(RNInt16), 1, fp);
        fwrite(ptr[i].color, sizeof(RNUChar8), 3, fp);
        fwrite(&ptr[i].flags, sizeof(RNUChar8), 1, fp);
      }
    }
    else if (major_version < 2) {
      for (int i = 0; i < count; i++) {
        fwrite(ptr[i].position, sizeof(RNScalar32), 3, fp);
        fwrite(ptr[i].color, sizeof(RNUChar8), 3, fp);
        fwrite(&ptr[i].flags, sizeof(RNUChar8), 1, fp);
      }
    }
  }
  
  // Swap endian back
  if (swap_endian) {
    for (int i = 0; i < count; i++) {
      RNSwap4(ptr[i].position, 3);
      RNSwap2(ptr[i].normal, 3);
      RNSwap2(ptr[i].tangent, 3);
      RNSwap2(ptr[i].radius, 2);
      RNSwap2(&ptr[i].depth, 1);
      RNSwap2(&ptr[i].elevation, 1);
      RNSwap4(&ptr[i].timestamp, 1);
      RNSwap4(&ptr[i].identifier, 1);
      RNSwap4(&ptr[i].attribute, 1);
    }
  }

  // Return status
  return status;
}

// Assembly:
subq $0x68, %rsp
movl 0x70(%rsp), %eax
movq %rdi, 0x60(%rsp)
movq %rsi, 0x58(%rsp)
movq %rdx, 0x50(%rsp)
movl %ecx, 0x4c(%rsp)
movl %r8d, 0x48(%rsp)
movl %r9d, 0x44(%rsp)
cmpl $0x0, 0x48(%rsp)
je 0x73a2b
movl $0x0, 0x40(%rsp)
movl 0x40(%rsp), %eax
cmpl 0x4c(%rsp), %eax
jge 0x73a29
movq 0x50(%rsp), %rdi
movslq 0x40(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
movl $0x3, %esi
callq 0x145690
movq 0x50(%rsp), %rdi
movslq 0x40(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x10, %rdi
movl $0x3, %esi
callq 0x145520
movq 0x50(%rsp), %rdi
movslq 0x40(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x16, %rdi
movl $0x3, %esi
callq 0x145520
movq 0x50(%rsp), %rdi
movslq 0x40(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x1c, %rdi
movl $0x2, %esi
callq 0x145520
movq 0x50(%rsp), %rdi
movslq 0x40(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x28, %rdi
movl $0x1, %esi
callq 0x145520
movq 0x50(%rsp), %rdi
movslq 0x40(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x2a, %rdi
movl $0x1, %esi
callq 0x145520
movq 0x50(%rsp), %rdi
movslq 0x40(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0xc, %rdi
movl $0x1, %esi
callq 0x145690
movq 0x50(%rsp), %rdi
movslq 0x40(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x20, %rdi
movl $0x1, %esi
callq 0x145690
movq 0x50(%rsp), %rdi
movslq 0x40(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x24, %rdi
movl $0x1, %esi
callq 0x145690
movl 0x40(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x40(%rsp)
jmp 0x738f8
jmp 0x73a2b
movl $0x0, 0x3c(%rsp)
movl 0x3c(%rsp), %eax
cmpl 0x4c(%rsp), %eax
jge 0x73a62
movq 0x50(%rsp), %rdi
movslq 0x3c(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
xorl %esi, %esi
callq 0x4fe30
movl 0x3c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c(%rsp)
jmp 0x73a33
movl $0x1, 0x38(%rsp)
movl 0x44(%rsp), %eax
cmpl 0x17fb14(%rip), %eax    # 0x1f3588
jne 0x73af0
movl 0x70(%rsp), %eax
cmpl 0x188b64(%rip), %eax    # 0x1fc5e4
jne 0x73af0
movl $0x0, 0x34(%rsp)
movl 0x34(%rsp), %eax
cmpl 0x4c(%rsp), %eax
jge 0x73aeb
movq 0x50(%rsp), %rdi
movl 0x4c(%rsp), %eax
subl 0x34(%rsp), %eax
movslq %eax, %rdx
movq 0x58(%rsp), %rcx
movl $0x30, %esi
callq 0x13a80
movq %rax, 0x28(%rsp)
cmpq $0x0, 0x28(%rsp)
jbe 0x73ad3
movq 0x28(%rsp), %rcx
movslq 0x34(%rsp), %rax
addq %rcx, %rax
movl %eax, 0x34(%rsp)
jmp 0x73ae9
leaq 0x1320aa(%rip), %rdi    # 0x1a5b84
movb $0x0, %al
callq 0x1464b0
movl $0x0, 0x38(%rsp)
jmp 0x73a8a
jmp 0x7402f
cmpl $0x5, 0x44(%rsp)
jne 0x73d0c
movl $0x0, 0x24(%rsp)
movl 0x24(%rsp), %eax
cmpl 0x4c(%rsp), %eax
jge 0x73d07
movl $0x0, 0x20(%rsp)
movq 0x50(%rsp), %rdi
movslq 0x24(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
callq 0x502f0
xorps %xmm1, %xmm1
ucomiss %xmm1, %xmm0
jne 0x73b3b
jp 0x73b3b
jmp 0x73b76
movq 0x50(%rsp), %rdi
movslq 0x24(%rsp), %rax
leaq (%rax,%rax,2), %rax
shlq $0x4, %rax
addq %rax, %rdi
callq 0x502f0
movss 0x131f3f(%rip), %xmm1   # 0x1a5a9c
mulss %xmm1, %xmm0
movss 0x131f37(%rip), %xmm1   # 0x1a5aa0
addss %xmm1, %xmm0
cvttss2si %xmm0, %rax
movl %eax, 0x20(%rsp)
movq 0x50(%rsp), %rdi
movslq 0x24(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
callq 0x50330
andl $0xffff, %eax           # imm = 0xFFFF
movl 0x20(%rsp), %ecx
shll $0x10, %ecx
orl %ecx, %eax
movl %eax, 0x1c(%rsp)
movq 0x50(%rsp), %rdi
movslq 0x24(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
movq 0x58(%rsp), %rcx
movl $0x4, %esi
movl $0x3, %edx
callq 0x13a80
movq 0x50(%rsp), %rdi
movslq 0x24(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0xc, %rdi
movq 0x58(%rsp), %rcx
movl $0x4, %esi
movl $0x1, %edx
callq 0x13a80
movq 0x50(%rsp), %rdi
movslq 0x24(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x10, %rdi
movq 0x58(%rsp), %rcx
movl $0x2, %esi
movl $0x3, %edx
callq 0x13a80
movq 0x50(%rsp), %rdi
movslq 0x24(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x16, %rdi
movq 0x58(%rsp), %rcx
movl $0x2, %esi
movl $0x3, %edx
callq 0x13a80
movq 0x50(%rsp), %rdi
movslq 0x24(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x1c, %rdi
movq 0x58(%rsp), %rcx
movl $0x2, %edx
movq %rdx, %rsi
callq 0x13a80
movq 0x50(%rsp), %rdi
movslq 0x24(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x20, %rdi
movq 0x58(%rsp), %rcx
movl $0x4, %esi
movl $0x1, %edx
callq 0x13a80
movq 0x58(%rsp), %rcx
leaq 0x1c(%rsp), %rdi
movl $0x4, %esi
movl $0x1, %edx
callq 0x13a80
movq 0x50(%rsp), %rdi
movslq 0x24(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x2c, %rdi
movq 0x58(%rsp), %rcx
movl $0x1, %esi
movl $0x3, %edx
callq 0x13a80
movq 0x50(%rsp), %rdi
movslq 0x24(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x2f, %rdi
movq 0x58(%rsp), %rcx
movl $0x1, %edx
movq %rdx, %rsi
callq 0x13a80
movl 0x24(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x24(%rsp)
jmp 0x73b03
jmp 0x7402d
cmpl $0x4, 0x44(%rsp)
jne 0x73e82
movl $0x0, 0x18(%rsp)
movl 0x18(%rsp), %eax
cmpl 0x4c(%rsp), %eax
jge 0x73e7d
movq 0x50(%rsp), %rdi
movslq 0x18(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
movq 0x58(%rsp), %rcx
movl $0x4, %esi
movl $0x3, %edx
callq 0x13a80
movq 0x50(%rsp), %rdi
movslq 0x18(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0xc, %rdi
movq 0x58(%rsp), %rcx
movl $0x4, %esi
movl $0x1, %edx
callq 0x13a80
movq 0x50(%rsp), %rdi
movslq 0x18(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x10, %rdi
movq 0x58(%rsp), %rcx
movl $0x2, %esi
movl $0x3, %edx
callq 0x13a80
movq 0x50(%rsp), %rdi
movslq 0x18(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x16, %rdi
movq 0x58(%rsp), %rcx
movl $0x2, %esi
movl $0x3, %edx
callq 0x13a80
movq 0x50(%rsp), %rdi
movslq 0x18(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x1c, %rdi
movq 0x58(%rsp), %rcx
movl $0x2, %edx
movq %rdx, %rsi
callq 0x13a80
movq 0x50(%rsp), %rdi
movslq 0x18(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x20, %rdi
movq 0x58(%rsp), %rcx
movl $0x4, %esi
movl $0x1, %edx
callq 0x13a80
movq 0x50(%rsp), %rdi
movslq 0x18(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x2c, %rdi
movq 0x58(%rsp), %rcx
movl $0x1, %esi
movl $0x3, %edx
callq 0x13a80
movq 0x50(%rsp), %rdi
movslq 0x18(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x2f, %rdi
movq 0x58(%rsp), %rcx
movl $0x1, %edx
movq %rdx, %rsi
callq 0x13a80
movl 0x18(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x18(%rsp)
jmp 0x73d1f
jmp 0x7402b
cmpl $0x3, 0x44(%rsp)
jne 0x73f7f
movl $0x0, 0x14(%rsp)
movl 0x14(%rsp), %eax
cmpl 0x4c(%rsp), %eax
jge 0x73f7a
movq 0x50(%rsp), %rdi
movslq 0x14(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
movq 0x58(%rsp), %rcx
movl $0x4, %esi
movl $0x3, %edx
callq 0x13a80
movq 0x50(%rsp), %rdi
movslq 0x14(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x10, %rdi
movq 0x58(%rsp), %rcx
movl $0x2, %esi
movl $0x3, %edx
callq 0x13a80
movq 0x50(%rsp), %rdi
movslq 0x14(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x1c, %rdi
movq 0x58(%rsp), %rcx
movl $0x2, %esi
movl $0x1, %edx
callq 0x13a80
movq 0x50(%rsp), %rdi
movslq 0x14(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x2c, %rdi
movq 0x58(%rsp), %rcx
movl $0x1, %esi
movl $0x3, %edx
callq 0x13a80
movq 0x50(%rsp), %rdi
movslq 0x14(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x2f, %rdi
movq 0x58(%rsp), %rcx
movl $0x1, %edx
movq %rdx, %rsi
callq 0x13a80
movl 0x14(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x14(%rsp)
jmp 0x73e95
jmp 0x74029
cmpl $0x2, 0x44(%rsp)
jae 0x74027
movl $0x0, 0x10(%rsp)
movl 0x10(%rsp), %eax
cmpl 0x4c(%rsp), %eax
jge 0x74025
movq 0x50(%rsp), %rdi
movslq 0x10(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
movq 0x58(%rsp), %rcx
movl $0x4, %esi
movl $0x3, %edx
callq 0x13a80
movq 0x50(%rsp), %rdi
movslq 0x10(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x2c, %rdi
movq 0x58(%rsp), %rcx
movl $0x1, %esi
movl $0x3, %edx
callq 0x13a80
movq 0x50(%rsp), %rdi
movslq 0x10(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x2f, %rdi
movq 0x58(%rsp), %rcx
movl $0x1, %edx
movq %rdx, %rsi
callq 0x13a80
movl 0x10(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x10(%rsp)
jmp 0x73f92
jmp 0x74027
jmp 0x74029
jmp 0x7402b
jmp 0x7402d
jmp 0x7402f
cmpl $0x0, 0x48(%rsp)
je 0x74175
movl $0x0, 0xc(%rsp)
movl 0xc(%rsp), %eax
cmpl 0x4c(%rsp), %eax
jge 0x74173
movq 0x50(%rsp), %rdi
movslq 0xc(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
movl $0x3, %esi
callq 0x145690
movq 0x50(%rsp), %rdi
movslq 0xc(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x10, %rdi
movl $0x3, %esi
callq 0x145520
movq 0x50(%rsp), %rdi
movslq 0xc(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x16, %rdi
movl $0x3, %esi
callq 0x145520
movq 0x50(%rsp), %rdi
movslq 0xc(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x1c, %rdi
movl $0x2, %esi
callq 0x145520
movq 0x50(%rsp), %rdi
movslq 0xc(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x28, %rdi
movl $0x1, %esi
callq 0x145520
movq 0x50(%rsp), %rdi
movslq 0xc(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x2a, %rdi
movl $0x1, %esi
callq 0x145520
movq 0x50(%rsp), %rdi
movslq 0xc(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0xc, %rdi
movl $0x1, %esi
callq 0x145690
movq 0x50(%rsp), %rdi
movslq 0xc(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x20, %rdi
movl $0x1, %esi
callq 0x145690
movq 0x50(%rsp), %rdi
movslq 0xc(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x24, %rdi
movl $0x1, %esi
callq 0x145690
movl 0xc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xc(%rsp)
jmp 0x74042
jmp 0x74175
movl 0x38(%rsp), %eax
addq $0x68, %rsp
retq
nop