// File: tomfunkhouser[P]gaps/pkgs/R3Surfels/R3SurfelDatabase.cpp
// Function: gaps::R3SurfelDatabase::ReadSurfel(_IO_FILE*, gaps::R3Surfel*, int, int, unsigned int, unsigned int) const
int R3SurfelDatabase::
ReadSurfel(FILE *fp, R3Surfel *ptr, int count, int swap_endian,
  unsigned int major_version, unsigned int minor_version) const
{
  // Check database version
  if ((major_version == current_major_version) && (minor_version == current_minor_version)) {
    int sofar = 0;
    while (sofar < count) {
      size_t status = fread(ptr, sizeof(R3Surfel), count - sofar, fp);
      if (status > 0) sofar += status;
      else { RNFail("Unable to read surfel from database file\n"); return 0; }
    }
  }
  else {
    if (major_version == 5) {
      for (int i = 0; i < count; i++) {
        RNUInt32 attribute;
        fread(ptr[i].position, sizeof(RNScalar32), 3, fp);
        fread(&ptr[i].timestamp, sizeof(RNScalar32), 1, fp);
        fread(ptr[i].normal, sizeof(RNInt16), 3, fp);
        fread(ptr[i].tangent, sizeof(RNInt16), 3, fp);
        fread(ptr[i].radius, sizeof(RNInt16), 2, fp);
        fread(&ptr[i].identifier, sizeof(RNUInt32), 1, fp);
        fread(&attribute, sizeof(RNUInt32), 1, fp);
        fread(ptr[i].color, sizeof(RNUChar8), 3, fp);
        fread(&ptr[i].flags, sizeof(RNUChar8), 1, fp);
        unsigned int encoded_elevation = (attribute >> 16) & 0xFFFF;
        if (encoded_elevation != 0) {
          float elevation = (encoded_elevation - 32768.0) / 400.0;
          ptr[i].SetElevation(elevation);
          ptr[i].SetAttribute(attribute & 0x0000FFFF);
        }
      }
    }
    else if (major_version == 4) {
      for (int i = 0; i < count; i++) {
        fread(ptr[i].position, sizeof(RNScalar32), 3, fp);
        fread(&ptr[i].timestamp, sizeof(RNScalar32), 1, fp);
        fread(ptr[i].normal, sizeof(RNInt16), 3, fp);
        fread(ptr[i].tangent, sizeof(RNInt16), 3, fp);
        fread(ptr[i].radius, sizeof(RNInt16), 2, fp);
        fread(&ptr[i].identifier, sizeof(RNUInt32), 1, fp);
        fread(ptr[i].color, sizeof(RNUChar8), 3, fp);
        fread(&ptr[i].flags, sizeof(RNUChar8), 1, fp);
      }
    }
    else if (major_version == 3) {
      for (int i = 0; i < count; i++) {
        fread(ptr[i].position, sizeof(RNScalar32), 3, fp);
        fread(ptr[i].normal, sizeof(RNInt16), 3, fp);
        fread(ptr[i].radius, sizeof(RNInt16), 1, fp);
        fread(ptr[i].color, sizeof(RNUChar8), 3, fp);
        fread(&ptr[i].flags, sizeof(RNUChar8), 1, fp);
        ptr[i].radius[1] = ptr[i].radius[0];
      }
    }
    else if (major_version < 2) {
      for (int i = 0; i < count; i++) {
        float position[3];
        unsigned char color_and_flags[4];
        fread(position, sizeof(RNScalar32), 3, fp);
        fread(color_and_flags, sizeof(RNUChar8), 4, fp);
        ptr[i].SetPosition(position);
        ptr[i].SetColor(color_and_flags);
        ptr[i].SetFlags(color_and_flags[3]);
      }
    }
  }

  // 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);
    }
  }

  // Return success
  return 1;
}

// Assembly:
subq $0x68, %rsp
movl 0x70(%rsp), %eax
movq %rdi, 0x58(%rsp)
movq %rsi, 0x50(%rsp)
movq %rdx, 0x48(%rsp)
movl %ecx, 0x44(%rsp)
movl %r8d, 0x40(%rsp)
movl %r9d, 0x3c(%rsp)
movl 0x3c(%rsp), %eax
cmpl 0x180409(%rip), %eax    # 0x1f3588
jne 0x73200
movl 0x70(%rsp), %eax
cmpl 0x189459(%rip), %eax    # 0x1fc5e4
jne 0x73200
movl $0x0, 0x38(%rsp)
movl 0x38(%rsp), %eax
cmpl 0x44(%rsp), %eax
jge 0x731fb
movq 0x48(%rsp), %rdi
movl 0x44(%rsp), %eax
subl 0x38(%rsp), %eax
movslq %eax, %rdx
movq 0x50(%rsp), %rcx
movl $0x30, %esi
callq 0x13860
movq %rax, 0x30(%rsp)
cmpq $0x0, 0x30(%rsp)
jbe 0x731de
movq 0x30(%rsp), %rcx
movslq 0x38(%rsp), %rax
addq %rcx, %rax
movl %eax, 0x38(%rsp)
jmp 0x731f9
leaq 0x132975(%rip), %rdi    # 0x1a5b5a
movb $0x0, %al
callq 0x1464b0
movl $0x0, 0x64(%rsp)
jmp 0x738ab
jmp 0x73195
jmp 0x7376a
cmpl $0x5, 0x3c(%rsp)
jne 0x7340f
movl $0x0, 0x2c(%rsp)
movl 0x2c(%rsp), %eax
cmpl 0x44(%rsp), %eax
jge 0x7340a
movq 0x48(%rsp), %rdi
movslq 0x2c(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
movq 0x50(%rsp), %rcx
movl $0x4, %esi
movl $0x3, %edx
callq 0x13860
movq 0x48(%rsp), %rdi
movslq 0x2c(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0xc, %rdi
movq 0x50(%rsp), %rcx
movl $0x4, %esi
movl $0x1, %edx
callq 0x13860
movq 0x48(%rsp), %rdi
movslq 0x2c(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x10, %rdi
movq 0x50(%rsp), %rcx
movl $0x2, %esi
movl $0x3, %edx
callq 0x13860
movq 0x48(%rsp), %rdi
movslq 0x2c(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x16, %rdi
movq 0x50(%rsp), %rcx
movl $0x2, %esi
movl $0x3, %edx
callq 0x13860
movq 0x48(%rsp), %rdi
movslq 0x2c(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x1c, %rdi
movq 0x50(%rsp), %rcx
movl $0x2, %edx
movq %rdx, %rsi
callq 0x13860
movq 0x48(%rsp), %rdi
movslq 0x2c(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x20, %rdi
movq 0x50(%rsp), %rcx
movl $0x4, %esi
movl $0x1, %edx
callq 0x13860
movq 0x50(%rsp), %rcx
leaq 0x28(%rsp), %rdi
movl $0x4, %esi
movl $0x1, %edx
callq 0x13860
movq 0x48(%rsp), %rdi
movslq 0x2c(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x2c, %rdi
movq 0x50(%rsp), %rcx
movl $0x1, %esi
movl $0x3, %edx
callq 0x13860
movq 0x48(%rsp), %rdi
movslq 0x2c(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x2f, %rdi
movq 0x50(%rsp), %rcx
movl $0x1, %edx
movq %rdx, %rsi
callq 0x13860
movl 0x28(%rsp), %eax
shrl $0x10, %eax
andl $0xffff, %eax           # imm = 0xFFFF
movl %eax, 0x24(%rsp)
cmpl $0x0, 0x24(%rsp)
je 0x733f8
movl 0x24(%rsp), %eax
cvtsi2sd %rax, %xmm0
movsd 0x1326c6(%rip), %xmm1   # 0x1a5a68
subsd %xmm1, %xmm0
movsd 0x131b22(%rip), %xmm1   # 0x1a4ed0
divsd %xmm1, %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x20(%rsp)
movq 0x48(%rsp), %rdi
movslq 0x2c(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
movss 0x20(%rsp), %xmm0
callq 0x47b90
movq 0x48(%rsp), %rdi
movslq 0x2c(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
movl 0x28(%rsp), %esi
andl $0xffff, %esi           # imm = 0xFFFF
callq 0x4faf0
jmp 0x733fa
movl 0x2c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2c(%rsp)
jmp 0x73213
jmp 0x73768
cmpl $0x4, 0x3c(%rsp)
jne 0x73585
movl $0x0, 0x1c(%rsp)
movl 0x1c(%rsp), %eax
cmpl 0x44(%rsp), %eax
jge 0x73580
movq 0x48(%rsp), %rdi
movslq 0x1c(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
movq 0x50(%rsp), %rcx
movl $0x4, %esi
movl $0x3, %edx
callq 0x13860
movq 0x48(%rsp), %rdi
movslq 0x1c(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0xc, %rdi
movq 0x50(%rsp), %rcx
movl $0x4, %esi
movl $0x1, %edx
callq 0x13860
movq 0x48(%rsp), %rdi
movslq 0x1c(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x10, %rdi
movq 0x50(%rsp), %rcx
movl $0x2, %esi
movl $0x3, %edx
callq 0x13860
movq 0x48(%rsp), %rdi
movslq 0x1c(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x16, %rdi
movq 0x50(%rsp), %rcx
movl $0x2, %esi
movl $0x3, %edx
callq 0x13860
movq 0x48(%rsp), %rdi
movslq 0x1c(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x1c, %rdi
movq 0x50(%rsp), %rcx
movl $0x2, %edx
movq %rdx, %rsi
callq 0x13860
movq 0x48(%rsp), %rdi
movslq 0x1c(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x20, %rdi
movq 0x50(%rsp), %rcx
movl $0x4, %esi
movl $0x1, %edx
callq 0x13860
movq 0x48(%rsp), %rdi
movslq 0x1c(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x2c, %rdi
movq 0x50(%rsp), %rcx
movl $0x1, %esi
movl $0x3, %edx
callq 0x13860
movq 0x48(%rsp), %rdi
movslq 0x1c(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x2f, %rdi
movq 0x50(%rsp), %rcx
movl $0x1, %edx
movq %rdx, %rsi
callq 0x13860
movl 0x1c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1c(%rsp)
jmp 0x73422
jmp 0x73766
cmpl $0x3, 0x3c(%rsp)
jne 0x736ac
movl $0x0, 0x18(%rsp)
movl 0x18(%rsp), %eax
cmpl 0x44(%rsp), %eax
jge 0x736a7
movq 0x48(%rsp), %rdi
movslq 0x18(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
movq 0x50(%rsp), %rcx
movl $0x4, %esi
movl $0x3, %edx
callq 0x13860
movq 0x48(%rsp), %rdi
movslq 0x18(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x10, %rdi
movq 0x50(%rsp), %rcx
movl $0x2, %esi
movl $0x3, %edx
callq 0x13860
movq 0x48(%rsp), %rdi
movslq 0x18(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x1c, %rdi
movq 0x50(%rsp), %rcx
movl $0x2, %esi
movl $0x1, %edx
callq 0x13860
movq 0x48(%rsp), %rdi
movslq 0x18(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x2c, %rdi
movq 0x50(%rsp), %rcx
movl $0x1, %esi
movl $0x3, %edx
callq 0x13860
movq 0x48(%rsp), %rdi
movslq 0x18(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x2f, %rdi
movq 0x50(%rsp), %rcx
movl $0x1, %edx
movq %rdx, %rsi
callq 0x13860
movq 0x48(%rsp), %rax
movslq 0x18(%rsp), %rcx
imulq $0x30, %rcx, %rcx
addq %rcx, %rax
movw 0x1c(%rax), %cx
movq 0x48(%rsp), %rax
movslq 0x18(%rsp), %rdx
imulq $0x30, %rdx, %rdx
addq %rdx, %rax
movw %cx, 0x1e(%rax)
movl 0x18(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x18(%rsp)
jmp 0x73598
jmp 0x73764
cmpl $0x2, 0x3c(%rsp)
jae 0x73762
movl $0x0, 0x14(%rsp)
movl 0x14(%rsp), %eax
cmpl 0x44(%rsp), %eax
jge 0x73760
leaq 0x8(%rsp), %rdi
movq 0x50(%rsp), %rcx
movl $0x4, %esi
movl $0x3, %edx
callq 0x13860
leaq 0x4(%rsp), %rdi
movq 0x50(%rsp), %rcx
movl $0x1, %esi
movl $0x4, %edx
callq 0x13860
movq 0x48(%rsp), %rdi
movslq 0x14(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
leaq 0x8(%rsp), %rsi
callq 0x501c0
movq 0x48(%rsp), %rdi
movslq 0x14(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
leaq 0x4(%rsp), %rsi
callq 0x44d10
movq 0x48(%rsp), %rdi
movslq 0x14(%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
movzbl 0x7(%rsp), %esi
callq 0x4fb30
movl 0x14(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x14(%rsp)
jmp 0x736bf
jmp 0x73762
jmp 0x73764
jmp 0x73766
jmp 0x73768
jmp 0x7376a
cmpl $0x0, 0x40(%rsp)
je 0x738a3
movl $0x0, (%rsp)
movl (%rsp), %eax
cmpl 0x44(%rsp), %eax
jge 0x738a1
movq 0x48(%rsp), %rdi
movslq (%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
movl $0x3, %esi
callq 0x145690
movq 0x48(%rsp), %rdi
movslq (%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x10, %rdi
movl $0x3, %esi
callq 0x145520
movq 0x48(%rsp), %rdi
movslq (%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x16, %rdi
movl $0x3, %esi
callq 0x145520
movq 0x48(%rsp), %rdi
movslq (%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x1c, %rdi
movl $0x2, %esi
callq 0x145520
movq 0x48(%rsp), %rdi
movslq (%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x28, %rdi
movl $0x1, %esi
callq 0x145520
movq 0x48(%rsp), %rdi
movslq (%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x2a, %rdi
movl $0x1, %esi
callq 0x145520
movq 0x48(%rsp), %rdi
movslq (%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0xc, %rdi
movl $0x1, %esi
callq 0x145690
movq 0x48(%rsp), %rdi
movslq (%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x20, %rdi
movl $0x1, %esi
callq 0x145690
movq 0x48(%rsp), %rdi
movslq (%rsp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
addq $0x24, %rdi
movl $0x1, %esi
callq 0x145690
movl (%rsp), %eax
addl $0x1, %eax
movl %eax, (%rsp)
jmp 0x7377c
jmp 0x738a3
movl $0x1, 0x64(%rsp)
movl 0x64(%rsp), %eax
addq $0x68, %rsp
retq
nopw %cs:(%rax,%rax)