// File: /workspace/github_cpp_makefile_star2_O2/tomfunkhouser[P]gaps/pkgs/GSV/GSVMesh.cpp
// Function: gaps::GSVMesh::LoadScan(gaps::GSVScan*, double, double)
int GSVMesh::
LoadScan(GSVScan *scan, 
  RNLength min_viewpoint_movement,
  RNLength max_depth_discontinuity)
{
  // Just checking
  if (!scan) return 0;
  if (scan->NScanlines() == 0) return 1;

  // Read points
  scan->ReadPoints();

  // Compute whether faces sould be flipped (clockwise)
  RNBoolean flip = (scan->SegmentIndex() == 2) ? 1 : 0;

  // Compute total number of vertices and length of scan viewpoint path
  int total_vertex_count = 0;
  RNScalar total_travel_distance = 0;
  R3Point prev_viewpoint = scan->Scanline(0)->Pose().Viewpoint();
  for (int ie = 0; ie < scan->NScanlines(); ie++) {
    GSVScanline *scanline = scan->Scanline(ie);
    const GSVPose& pose = scanline->Pose();
    const R3Point& viewpoint = pose.Viewpoint();
    RNLength movement = R3Distance(viewpoint, prev_viewpoint);
    total_travel_distance += movement;
    if (movement < min_viewpoint_movement) continue;
    prev_viewpoint = viewpoint;
    total_vertex_count += scanline->NPoints();
  }

  // Compute number of rows and columns
  if (total_travel_distance == 0) { scan->ReleasePoints(); return 1; }
  int ncols = (int) (total_travel_distance / min_viewpoint_movement + 0.5);
  if (ncols == 0) { scan->ReleasePoints(); return 1; }
  const int nrows = 180;
  int col = 0;

  // Allocate vertex data
  gsv_vertex_block = new GSVMeshVertex [ total_vertex_count ];
  if (!gsv_vertex_block) { 
    RNFail("Unable to allocate GSV Mesh vertex array\n"); 
    scan->ReleasePoints(); 
    return 0; 
  }

  // Initialize vertex buffer
  int buffer_index = 0;
  GSVMeshVertex *vertex_buffer[2][nrows];
  for (int k = 0; k < nrows; k++) {
    vertex_buffer[0][k] = NULL;
    vertex_buffer[1][k] = NULL;
  }

  // Create mesh
  int vertex_count = 0;
  prev_viewpoint = scan->Scanline(0)->Pose().Viewpoint();
  for (int ie = 0; ie < scan->NScanlines(); ie++) {
    GSVScanline *scanline = scan->Scanline(ie);
    const GSVPose& pose = scanline->Pose();
    const R3Point& viewpoint = pose.Viewpoint();
    RNLength movement = R3Distance(viewpoint, prev_viewpoint);
    if (movement < min_viewpoint_movement) continue;
    prev_viewpoint = viewpoint;
    const R3Vector& towards = pose.Towards();
    R3Vector up = pose.Up();

    // Initialize buffer of vertices in scanline indexed by row
    for (int k = 0; k < nrows; k++) {
      vertex_buffer[buffer_index][k] = NULL;
    }

    // Create vertices for scanline
    for (int j = 0; j < scanline->NPoints(); j++) {
      R3Point position = scanline->PointPosition(j);
      R3Vector v = position - viewpoint;
      RNLength distance = v.Length();
      if (RNIsZero(distance)) continue;
      v /= distance;
      RNScalar dot = v.Dot(towards);
      RNAngle angle = acos(dot);
      if (v.Dot(up) > 0) angle = RN_PI_OVER_TWO + angle;
      else angle = RN_PI_OVER_TWO - angle;
      int row = (int) (nrows * angle / RN_PI + 0.5);
      if ((row < 0) || (row >= nrows)) continue;
      if (vertex_buffer[buffer_index][row]) continue;
      assert(vertex_count < total_vertex_count);
      GSVMeshVertex *vertex = &gsv_vertex_block[vertex_count];
      vertex_buffer[buffer_index][row] = vertex;
      CreateVertex(position, vertex);
      vertex->scanline = scanline;
      vertex->point_index = j;
      vertex->boundary_type = GSV_MESH_NO_BOUNDARY;
      if (j == 0) vertex->boundary_type = GSV_MESH_BOTTOM_BOUNDARY;
      else if (j == (scanline->NPoints()-1)) vertex->boundary_type = GSV_MESH_TOP_BOUNDARY;
      else if (ie == 0) vertex->boundary_type = GSV_MESH_LEFT_BOUNDARY;
      else if (ie == (scan->NScanlines()-1)) vertex->boundary_type = GSV_MESH_RIGHT_BOUNDARY;
      vertex_count++;
    }

    // Create faces between this and previous scanline
    if (col > 0) {
      int row0 = 0;
      int row1 = 0;
      while ((row0 < nrows) && (!vertex_buffer[1-buffer_index][row0])) row0++;
      while ((row1 < nrows) && (!vertex_buffer[buffer_index][row1])) row1++;
      if ((row0 < nrows) && (row1 < nrows)) {
        GSVMeshVertex *vertex0 = vertex_buffer[1-buffer_index][row0];
        GSVMeshVertex *vertex1 = vertex_buffer[buffer_index][row1];
        while ((row0 < nrows-1) || (row1 < nrows-1)) {
          // Get next vertex
          int row = 0;
          GSVMeshVertex *vertex = NULL;
          if (row0 < row1) {
            row0++;
            vertex = vertex_buffer[1-buffer_index][row0];
            row = 0;
          }
          else {
            row1++;
            vertex = vertex_buffer[buffer_index][row1];
            row = 1;
          }

          // Check vertex
          if (vertex && vertex0 && vertex1) {
            // Mark vertex types
            RNBoolean curtain = FALSE;
            RNLength depth = VertexLaserDepth(vertex);
            RNLength depth0 = VertexLaserDepth(vertex0);
            RNLength depth1 = VertexLaserDepth(vertex1);
            if (max_depth_discontinuity > 0) {
              const R3Point& position0 = VertexPosition(vertex0);
              const R3Point& position1 = VertexPosition(vertex1);
              R3Vector normal_vector0 = VertexNormal(vertex0);
              R3Vector normal_vector1 = VertexNormal(vertex1);
              R3Vector normal_vector = 0.5 * (normal_vector0 + normal_vector1);
              normal_vector.Normalize();
              R3Vector laser_vector0 = VertexLaserViewpoint(vertex0) - position0;
              laser_vector0.Normalize();
              R3Vector laser_vector1 = VertexLaserViewpoint(vertex1)- position1;
              laser_vector1.Normalize();
              R3Vector laser_vector = 0.5 * (laser_vector0 + laser_vector1);
              laser_vector.Normalize();
              RNScalar dot = fabs(laser_vector.Dot(normal_vector));
              if (dot < 0.5) dot = 0.5;
              RNLength max_depth_diff = max_depth_discontinuity / dot;
              if (depth - depth0 > max_depth_diff) {
                vertex0->boundary_type = GSV_MESH_SILHOUETTE_BOUNDARY;
                vertex->boundary_type = GSV_MESH_SHADOW_BOUNDARY;
                curtain = TRUE;
              }
              else if (depth0 - depth > max_depth_diff) {
                vertex->boundary_type = GSV_MESH_SILHOUETTE_BOUNDARY;
                vertex0->boundary_type = GSV_MESH_SHADOW_BOUNDARY;
                curtain = TRUE;
              }
              if (depth - depth1 > max_depth_diff) {
                vertex1->boundary_type = GSV_MESH_SILHOUETTE_BOUNDARY;
                vertex->boundary_type = GSV_MESH_SHADOW_BOUNDARY;
                curtain = TRUE;
              }
              else if (depth1 - depth > max_depth_diff) {
                vertex->boundary_type = GSV_MESH_SILHOUETTE_BOUNDARY;
                vertex1->boundary_type = GSV_MESH_SHADOW_BOUNDARY;
                curtain = TRUE;
              }
            }
            
            // Create face
            if (!curtain) {
              R3MeshFace *face = NULL;
              if (flip) face = CreateFace(vertex0, vertex, vertex1);
              else face = CreateFace(vertex0, vertex1, vertex);
              if (face) SetFaceSegment(face, 1);
            }
          }
          
          // Update stuff for next triangle
          if (vertex) {
            if (row == 0) vertex0 = vertex;
            else vertex1 = vertex;
          }
        }
      }
    }

    // Update stuff for next scanline
    buffer_index = 1 - buffer_index;
    col++;
  }

  // Release points
  scan->ReleasePoints(); 

  // Return success
  return 1;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xce8, %rsp            # imm = 0xCE8
movsd %xmm1, 0x60(%rsp)
movsd %xmm0, 0x48(%rsp)
movq %rdi, 0x38(%rsp)
testq %rsi, %rsi
je 0x40001
movq %rsi, %r13
pushq $0x1
popq %rax
cmpl $0x0, 0x34(%rsi)
je 0x4076d
movq %r13, %rdi
callq 0x3d614
movq %r13, %rdi
callq 0x3cecc
movl %eax, 0x5c(%rsp)
movq 0x28(%r13), %rax
movq (%rax), %rsi
addq $0x40, %rsi
leaq 0x128(%rsp), %rbx
movq %rbx, %rdi
callq 0xc0e0c
xorl %r15d, %r15d
xorpd %xmm1, %xmm1
xorl %ebp, %ebp
movslq 0x34(%r13), %rax
cmpq %rax, %r15
jge 0x3ffed
movsd %xmm1, 0x10(%rsp)
movq 0x28(%r13), %rax
movq (%rax,%r15,8), %r12
leaq 0x40(%r12), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x8e602
movapd %xmm0, %xmm2
movsd 0x48(%rsp), %xmm0
ucomisd %xmm2, %xmm0
ja 0x3ffde
movq %rbx, %rdi
movq %r14, %rsi
movsd %xmm2, 0x50(%rsp)
callq 0xc10e6
movsd 0x50(%rsp), %xmm2
addl 0x30(%r12), %ebp
movsd 0x10(%rsp), %xmm1
addsd %xmm2, %xmm1
incq %r15
jmp 0x3ff8b
xorpd %xmm0, %xmm0
ucomisd %xmm0, %xmm1
jne 0x40008
jp 0x40008
movq %r13, %rdi
jmp 0x40765
xorl %eax, %eax
jmp 0x4076d
divsd 0x48(%rsp), %xmm1
addsd 0xeb022(%rip), %xmm1    # 0x12b038
cvttsd2si %xmm1, %eax
testl %eax, %eax
je 0x3fff9
movq %r13, 0x40(%rsp)
movslq %ebp, %r14
movl $0xa8, %ecx
movq %r14, %rax
mulq %rcx
movq %rax, %rbx
seto %al
addq $0x8, %rbx
pushq $-0x1
popq %rcx
cmovbq %rcx, %rbx
testb %al, %al
cmovneq %rcx, %rbx
movq %rbx, %rdi
callq 0x27040
movq %r14, (%rax)
leaq 0x8(%rax), %r13
testl %r14d, %r14d
je 0x40087
movq %rax, %r15
imulq $-0xa8, %r14, %rbp
xorl %r12d, %r12d
movq %r13, %r14
movq %r14, %rdi
callq 0x41c10
addq $-0xa8, %r12
addq $0xa8, %r14
cmpq %r12, %rbp
jne 0x4006c
movq 0x38(%rsp), %rax
movq %r13, 0x138(%rax)
xorl %eax, %eax
movq 0x40(%rsp), %r14
cmpq $0xb4, %rax
je 0x400b9
andq $0x0, 0x1a0(%rsp,%rax,8)
andq $0x0, 0x740(%rsp,%rax,8)
incq %rax
jmp 0x4009a
movq 0x28(%r14), %rax
movq (%rax), %rsi
addq $0x40, %rsi
leaq 0x128(%rsp), %r12
movq %r12, %rdi
callq 0xc10e6
leaq 0xf712d(%rip), %rax     # 0x137208
movsd (%rax), %xmm0
movsd %xmm0, 0x50(%rsp)
leaq 0xf710c(%rip), %rax     # 0x1371f8
movsd (%rax), %xmm0
movsd %xmm0, 0xa8(%rsp)
xorl %ebp, %ebp
movl $0x0, 0x34(%rsp)
xorl %r13d, %r13d
movl $0x0, 0x2c(%rsp)
movslq 0x34(%r14), %rax
cmpq %rax, %rbp
jge 0x40762
movq 0x28(%r14), %rax
movq (%rax,%rbp,8), %rbx
leaq 0x40(%rbx), %r15
movq %r15, %rdi
movq %r12, %rsi
callq 0x8e602
movsd 0x48(%rsp), %xmm1
ucomisd %xmm0, %xmm1
ja 0x4075a
leaq 0x38(%rbx), %r14
movq %r12, %rdi
movq %r15, %rsi
callq 0xc10e6
leaq 0x188(%rsp), %rdi
movq %r14, %rsi
callq 0x41e74
leaq 0x170(%rsp), %rdi
movq %r14, %rsi
callq 0x41eba
movl %r13d, %eax
movq %rax, 0x90(%rsp)
imulq $0x5a0, %rax, %rax      # imm = 0x5A0
leaq (%rsp,%rax), %r12
addq $0x1a0, %r12            # imm = 0x1A0
xorl %eax, %eax
cmpq $0xb4, %rax
je 0x401a2
andq $0x0, (%r12,%rax,8)
incq %rax
jmp 0x40190
movl %r13d, 0x8(%rsp)
xorl %r13d, %r13d
movq %rbp, 0x68(%rsp)
cmpl 0x30(%rbx), %r13d
jge 0x40356
leaq 0xc8(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rsi
movl %r13d, %edx
callq 0x3f9e0
leaq 0x110(%rsp), %rbp
movq %rbp, %rdi
movq %r14, %rsi
movq %r15, %rdx
callq 0xc0fd9
movq %rbp, %rdi
callq 0xc16c2
leaq 0x17f284(%rip), %rax    # 0x1bf478
movsd (%rax), %xmm1
movapd %xmm1, %xmm2
xorpd 0xebabc(%rip), %xmm2    # 0x12bcc0
ucomisd %xmm2, %xmm0
jb 0x40214
ucomisd %xmm0, %xmm1
jae 0x4034e
leaq 0x110(%rsp), %r14
movq %r14, %rdi
callq 0xc1eba
movq %r14, %rdi
leaq 0x188(%rsp), %rsi
callq 0xc1836
callq 0x278c0
movapd %xmm0, 0x10(%rsp)
movq %r14, %rdi
leaq 0x170(%rsp), %rsi
callq 0xc1836
xorpd %xmm1, %xmm1
cmpltsd %xmm0, %xmm1
movapd %xmm1, %xmm0
movapd 0x10(%rsp), %xmm2
andpd %xmm2, %xmm0
xorpd 0xeba52(%rip), %xmm2    # 0x12bcc0
andnpd %xmm2, %xmm1
orpd %xmm0, %xmm1
addsd 0x50(%rsp), %xmm1
mulsd 0xeba2c(%rip), %xmm1    # 0x12bcb0
divsd 0xa8(%rsp), %xmm1
addsd 0xeada3(%rip), %xmm1    # 0x12b038
cvttsd2si %xmm1, %eax
cmpl $0xb3, %eax
ja 0x4034e
movl %eax, %eax
cmpq $0x0, (%r12,%rax,8)
jne 0x4034e
leaq (%r12,%rax,8), %rax
movq 0x38(%rsp), %rdi
movq 0x138(%rdi), %rbp
movslq 0x34(%rsp), %rcx
imulq $0xa8, %rcx, %r14
leaq (%r14,%rbp), %rdx
movq %rdx, (%rax)
movq (%rdi), %rax
leaq 0xc8(%rsp), %rsi
movq %rdx, 0x10(%rsp)
callq *0x20(%rax)
movq %rbx, 0x98(%rbp,%r14)
movl %r13d, 0xa0(%rbp,%r14)
andl $0x0, 0xa4(%rbp,%r14)
movq 0x68(%rsp), %rsi
pushq $0x3
popq %rax
testl %r13d, %r13d
je 0x4033f
testq %rsi, %rsi
sete %dl
movl 0x30(%rbx), %ecx
decl %ecx
xorl %eax, %eax
cmpl %ecx, %r13d
sete %cl
orb %cl, %dl
je 0x4032d
movb %cl, %al
leal (%rax,%rax,2), %eax
incl %eax
jmp 0x4033f
movq 0x40(%rsp), %rax
movl 0x34(%rax), %ecx
decl %ecx
pushq $0x2
popq %rax
cmpq %rcx, %rsi
jne 0x4034a
movq 0x10(%rsp), %rcx
movl %eax, 0xa4(%rcx)
incl 0x34(%rsp)
incl %r13d
jmp 0x401af
pushq $0x1
popq %rax
subl 0x8(%rsp), %eax
movl %eax, 0x30(%rsp)
cmpl $0x0, 0x2c(%rsp)
movl $0xb3, %r13d
jle 0x4073f
movl 0x30(%rsp), %eax
movq %rax, 0x88(%rsp)
imulq $0x5a0, %rax, %rax      # imm = 0x5A0
addq %rsp, %rax
addq $0x1a0, %rax            # imm = 0x1A0
xorl %r14d, %r14d
cmpq $0xb4, %r14
je 0x403a6
cmpq $0x0, (%rax,%r14,8)
jne 0x403b0
incq %r14
jmp 0x40391
movl $0xb4, %r14d
xorl %ecx, %ecx
jmp 0x403ba
cmpq $0xb4, %r14
setb %cl
xorl %ebp, %ebp
cmpq $0xb4, %rbp
je 0x4073f
cmpq $0x0, (%r12,%rbp,8)
jne 0x403d5
incq %rbp
jmp 0x403bc
testb %cl, %cl
je 0x4073f
movl %r14d, %ecx
movq (%rax,%rcx,8), %rsi
movq (%r12,%rbp,8), %rcx
cmpl %r13d, %r14d
setl %al
cmpl %r13d, %ebp
setl %dl
orb %al, %dl
cmpb $0x1, %dl
jne 0x4073f
movl %ebp, %r12d
movl %r14d, %ebx
cmpl %ebp, %r14d
jge 0x4041d
leal 0x1(%rbx), %eax
movq 0x88(%rsp), %rdx
movl %eax, %r14d
movl %r12d, %ebp
jmp 0x4042f
leal 0x1(%r12), %eax
movq 0x90(%rsp), %rdx
movl %ebx, %r14d
movl %eax, %ebp
cltq
imulq $0x5a0, %rdx, %rdx      # imm = 0x5A0
addq %rsp, %rdx
addq $0x1a0, %rdx            # imm = 0x1A0
movq (%rdx,%rax,8), %r15
testq %r15, %r15
je 0x4071b
testq %rsi, %rsi
je 0x4071b
testq %rcx, %rcx
je 0x4071b
movq %rsi, 0x10(%rsp)
movq %r15, %rsi
movq %rcx, 0x8(%rsp)
callq 0x3fde8
movsd %xmm0, 0x98(%rsp)
movq 0x10(%rsp), %rsi
callq 0x3fde8
movsd %xmm0, 0xa0(%rsp)
movq 0x8(%rsp), %rsi
callq 0x3fde8
movq 0x8(%rsp), %rcx
movq 0x10(%rsp), %rsi
movapd %xmm0, %xmm1
movsd 0x60(%rsp), %xmm0
ucomisd 0xeac43(%rip), %xmm0    # 0x12b0f8
jbe 0x406df
movsd %xmm1, 0x80(%rsp)
leaq 0x18(%rsi), %rax
movq %rax, 0x70(%rsp)
leaq 0x18(%rcx), %rax
movq %rax, 0x78(%rsp)
movq 0x38(%rsp), %r13
movq %r13, %rdi
movq 0x10(%rsp), %rsi
callq 0x30eae
leaq 0xc8(%rsp), %rdi
movq %rax, %rsi
callq 0xc15cc
movq %r13, %rdi
movq 0x8(%rsp), %rsi
callq 0x30eae
leaq 0x110(%rsp), %r13
movq %r13, %rdi
movq %rax, %rsi
callq 0xc15cc
leaq 0xb0(%rsp), %rdi
leaq 0xc8(%rsp), %rsi
movq %r13, %rdx
callq 0xc1f42
leaq 0x158(%rsp), %r13
movq %r13, %rdi
leaq 0xb0(%rsp), %rsi
movsd 0xeaaed(%rip), %xmm0    # 0x12b038
callq 0xc1cb2
movq %r13, %rdi
callq 0xc18be
leaq 0xf8(%rsp), %rdi
movq 0x10(%rsp), %rdx
callq 0x3fe76
leaq 0xb0(%rsp), %r13
movq %r13, %rdi
leaq 0xf8(%rsp), %rsi
movq 0x70(%rsp), %rdx
callq 0xc0fd9
movq %r13, %rdi
callq 0xc18be
leaq 0xe0(%rsp), %rdi
movq 0x8(%rsp), %rdx
callq 0x3fe76
leaq 0xf8(%rsp), %r13
movq %r13, %rdi
leaq 0xe0(%rsp), %rsi
movq 0x78(%rsp), %rdx
callq 0xc0fd9
movq %r13, %rdi
callq 0xc18be
leaq 0x140(%rsp), %rdi
leaq 0xb0(%rsp), %rsi
movq %r13, %rdx
callq 0xc1f42
leaq 0xe0(%rsp), %r13
movq %r13, %rdi
leaq 0x140(%rsp), %rsi
movsd 0xeaa3f(%rip), %xmm0    # 0x12b038
callq 0xc1cb2
movq %r13, %rdi
callq 0xc18be
movq %r13, %rdi
leaq 0x158(%rsp), %rsi
callq 0xc1836
movq 0x10(%rsp), %rsi
andpd 0xeb89d(%rip), %xmm0    # 0x12bec0
movsd 0xeaa0d(%rip), %xmm1    # 0x12b038
maxsd %xmm0, %xmm1
movsd 0x60(%rsp), %xmm0
divsd %xmm1, %xmm0
movsd 0x98(%rsp), %xmm2
movapd %xmm2, %xmm1
movsd 0xa0(%rsp), %xmm3
subsd %xmm3, %xmm1
ucomisd %xmm0, %xmm1
movq %rsi, %rcx
movq %r15, %rdx
ja 0x40671
subsd %xmm2, %xmm3
movb $0x1, %al
ucomisd %xmm0, %xmm3
movq %r15, %rcx
movq %rsi, %rdx
jbe 0x40687
movl $0x6, 0xa4(%rcx)
movl $0x5, 0xa4(%rdx)
xorl %eax, %eax
movapd %xmm2, %xmm1
movsd 0x80(%rsp), %xmm3
subsd %xmm3, %xmm1
ucomisd %xmm0, %xmm1
movq 0x8(%rsp), %rcx
movq %rcx, %rdi
movq %r15, %rdx
ja 0x406b9
subsd %xmm2, %xmm3
ucomisd %xmm0, %xmm3
movq %r15, %rdi
movq %rcx, %rdx
jbe 0x406d5
movl $0x6, 0xa4(%rdi)
movl $0x5, 0xa4(%rdx)
movl $0xb3, %r13d
jmp 0x4071b
testb %al, %al
movl $0xb3, %r13d
je 0x4071b
movq 0x38(%rsp), %rdi
movq (%rdi), %rax
movq 0x48(%rax), %rax
cmpl $0x2, 0x5c(%rsp)
jne 0x406f7
movq %r15, %rdx
jmp 0x406fd
movq %rcx, %rdx
movq %r15, %rcx
xorl %r8d, %r8d
callq *%rax
testq %rax, %rax
movq 0x10(%rsp), %rsi
movq 0x8(%rsp), %rcx
je 0x4071b
movl $0x1, 0x9c(%rax)
testq %r15, %r15
movq %rsi, %rax
cmovneq %r15, %rax
cmpl %r12d, %ebx
movq %r15, %rdx
cmovlq %rcx, %rdx
cmovlq %rax, %rsi
testq %r15, %r15
cmovneq %rdx, %rcx
jmp 0x403e8
incl 0x2c(%rsp)
movl 0x30(%rsp), %r13d
movq 0x40(%rsp), %r14
leaq 0x128(%rsp), %r12
movq 0x68(%rsp), %rbp
incq %rbp
jmp 0x4010e
movq %r14, %rdi
callq 0x3d6e4
pushq $0x1
popq %rax
addq $0xce8, %rsp            # imm = 0xCE8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %r14
testq %r12, %r12
je 0x407a6
negq %r12
movq %r15, %r13
addq $-0xa0, %r13
leaq (%r12,%r13), %rdi
callq 0xa2f5c
addq $-0xa8, %r12
jne 0x40794
movq %r15, %rdi
movq %rbx, %rsi
callq 0x28360
movq %r14, %rdi
callq 0x28170
nop