// File: tomfunkhouser[P]gaps/pkgs/R3Shapes/R3Mesh.cpp
// Function: gaps::R3Mesh::TracePath(gaps::R3MeshVertex const*, gaps::R3Vector const&, double, gaps::R3Point*, gaps::R3MeshFace**, gaps::R3MeshIntersection*, int*) const
RNLength R3Mesh::
TracePath(const R3MeshVertex *source_vertex, const R3Vector& tangent_direction, RNLength max_distance,
  R3Point *final_position, R3MeshFace **final_face, R3MeshIntersection *intersections, int *nintersections) const
{
  // Increment mesh mark (used to avoid visiting same edge/face twice in recursive function)
  R3Mesh *mesh = (R3Mesh *) this;
  R3mesh_mark++;

  // Initialize result
  if (final_position) *final_position = VertexPosition(source_vertex);
  if (final_face) *final_face = NULL;
  if (nintersections) *nintersections = 0;
  if (max_distance <= 0) return 0;

  // Get convenient variables
  const R3Point& source_position = VertexPosition(source_vertex);
  R3Vector source_normal = VertexNormal(source_vertex);
  R3Vector split_direction = tangent_direction % source_normal;
  RNLength split_direction_length = split_direction.Length();
  if (split_direction_length == 0) return 0;
  split_direction /= split_direction_length;
  R3Plane split_plane(source_position, split_direction);

  // Find first face, edge, and position
  R3MeshFace *cur_face = NULL;
  R3MeshEdge *cur_edge = NULL;
  R3Point cur_position = R3zero_point;
  for (int i = 0; i < VertexValence(source_vertex); i++) {
    R3MeshEdge *cw_edge = EdgeOnVertex(source_vertex, i);
    R3MeshEdge *ccw_edge = EdgeOnVertex(source_vertex, cw_edge, RN_CCW);
    R3MeshFace *face = FaceOnVertex(source_vertex, cw_edge, RN_CCW);
    if (!face) continue;
    R3MeshEdge *edge = EdgeAcrossFace(face, source_vertex);

    // Check position of cw_vertex
    R3MeshVertex *cw_vertex = VertexAcrossEdge(cw_edge, source_vertex);
    const R3Point& cw_position = VertexPosition(cw_vertex);
    RNScalar cw_d = R3SignedDistance(split_plane, cw_position);
    if (cw_d == 0) {
      cur_position = cw_position;
      cur_face = face;
      cur_edge = edge;
      break;
    }

    // Check position of ccw_vertex
    R3MeshVertex *ccw_vertex = VertexAcrossEdge(ccw_edge, source_vertex);
    const R3Point& ccw_position = VertexPosition(ccw_vertex);
    RNScalar ccw_d = R3SignedDistance(split_plane, ccw_position);
    if (ccw_d == 0) {
      cur_position = ccw_position;
      cur_face = face;
      cur_edge = edge;
      break;
    }

    // Check if source direction splits cw and ccw vertices
    if ((cw_d > 0)  && (ccw_d < 0)) {
      RNScalar t = cw_d / (cw_d - ccw_d);
      cur_position = cw_position + t * (ccw_position - cw_position);
      cur_face = face;
      cur_edge = edge;
      break;
    }
  }      

  // Get next distance and direction
  RNLength cur_distance = R3Distance(cur_position, source_position);
  R3Vector cur_direction = cur_position - source_position; cur_direction.Normalize();

  // Check if found next face
  if (!cur_face) return 0;

  // Check if max_distance lies within next face
  if (cur_distance >= max_distance) {
    RNScalar t = max_distance / cur_distance;
    if (final_position) *final_position = (1-t)*source_position + t*cur_position;
    if (final_face) *final_face = cur_face;
    return max_distance;
  }

  // Trace path
  while (TRUE) {
    // Mark cur edge and face
    mesh->SetEdgeMark(cur_edge, R3mesh_mark);
    mesh->SetFaceMark(cur_face, R3mesh_mark);

    // Add intersection
    if (intersections && nintersections) {
      intersections[*nintersections].type = R3_MESH_EDGE_TYPE;
      intersections[*nintersections].vertex = NULL;
      intersections[*nintersections].edge = cur_edge;
      intersections[*nintersections].face = cur_face;
      intersections[*nintersections].point = cur_position;
      intersections[*nintersections].t = cur_distance;
      (*nintersections)++;
    }

    // Get next face
    R3MeshFace *next_face = FaceAcrossEdge(cur_edge, cur_face);
    if (!next_face) {
      if (final_position) *final_position = cur_position;
      if (final_face) *final_face = cur_face;
      return cur_distance;
    }
    
    // Get next direction 
    R3Vector cur_face_normal = FaceNormal(cur_face);
    R3Vector next_face_normal = FaceNormal(next_face);
    R4Matrix matrix = R4identity_matrix;
    matrix.Rotate(cur_face_normal, next_face_normal);
    R3Vector next_direction = matrix * cur_direction;
    next_direction.Normalize();
    
    // Get plane splitting next face along next_direction
    R3Vector split_plane_normal = next_face_normal % next_direction;  
    split_plane_normal.Normalize();
    R3Plane split_plane(cur_position, split_plane_normal);
    
    // Get next edge and position
    R3MeshVertex *vertex = VertexAcrossFace(next_face, cur_edge);
    R3Point next_position = VertexPosition(vertex);
    RNScalar d = R3SignedDistance(split_plane, next_position);
    R3MeshEdge *next_edge = EdgeOnFace(next_face, cur_edge, (d < 0) ? RN_CW : RN_CCW);
    if (d != 0) {
      // Split does not hit vertex
      R3Vector next_edge_vector = EdgeVector(next_edge);
      RNScalar denom = split_plane.Normal().Dot(next_edge_vector);
      if (denom != 0) {
        R3Point next_edge_start = VertexPosition(VertexOnEdge(next_edge, 0));
        RNScalar t = -(R3SignedDistance(split_plane, next_edge_start)) / denom;
        next_position = next_edge_start + next_edge_vector * t;
      }
    }

    // Get next distance
    RNLength next_distance = cur_distance + R3Distance(cur_position, next_position);
    if (next_distance >= max_distance) {
      assert(next_distance > cur_distance);
      RNScalar t = (max_distance - cur_distance) / (next_distance - cur_distance);
      if (final_position) *final_position = (1-t)*cur_position + t*next_position;
      if (final_face) *final_face = next_face;
      return max_distance;
    }

    // Go to next face
    cur_edge = next_edge;
    cur_face = next_face;
    cur_position = next_position;
    cur_direction = next_direction;
    cur_distance = next_distance;
  }

  // Return error
  return -1;
}

// Assembly:
subq $0x418, %rsp            # imm = 0x418
movq 0x420(%rsp), %rax
movq %rdi, 0x408(%rsp)
movq %rsi, 0x400(%rsp)
movq %rdx, 0x3f8(%rsp)
movsd %xmm0, 0x3f0(%rsp)
movq %rcx, 0x3e8(%rsp)
movq %r8, 0x3e0(%rsp)
movq %r9, 0x3d8(%rsp)
movq 0x408(%rsp), %rax
movq %rax, 0x28(%rsp)
movq %rax, 0x3d0(%rsp)
movl 0x14683d(%rip), %eax    # 0x16f520
addl $0x1, %eax
movl %eax, 0x146834(%rip)    # 0x16f520
cmpq $0x0, 0x3e8(%rsp)
je 0x28d19
movq 0x28(%rsp), %rdi
movq 0x400(%rsp), %rsi
callq 0x13660
movq %rax, %rsi
movq 0x3e8(%rsp), %rdi
callq 0x6f1e0
cmpq $0x0, 0x3e0(%rsp)
je 0x28d33
movq 0x3e0(%rsp), %rax
movq $0x0, (%rax)
cmpq $0x0, 0x420(%rsp)
je 0x28d4c
movq 0x420(%rsp), %rax
movl $0x0, (%rax)
xorps %xmm0, %xmm0
ucomisd 0x3f0(%rsp), %xmm0
jb 0x28d6b
xorps %xmm0, %xmm0
movsd %xmm0, 0x410(%rsp)
jmp 0x298d4
movq 0x28(%rsp), %rdi
movq 0x400(%rsp), %rsi
callq 0x13660
movq 0x28(%rsp), %rdi
movq %rax, 0x3c8(%rsp)
movq 0x400(%rsp), %rsi
callq 0x36860
movq %rax, %rsi
leaq 0x3b0(%rsp), %rdi
callq 0x6fcf0
movq 0x3f8(%rsp), %rsi
leaq 0x398(%rsp), %rdi
leaq 0x3b0(%rsp), %rdx
callq 0x70af0
leaq 0x398(%rsp), %rdi
callq 0x6fe90
movsd %xmm0, 0x390(%rsp)
movsd 0x390(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x28dff
jp 0x28dff
xorps %xmm0, %xmm0
movsd %xmm0, 0x410(%rsp)
jmp 0x298d4
movsd 0x390(%rsp), %xmm0
leaq 0x398(%rsp), %rdi
callq 0x70ec0
movq 0x3c8(%rsp), %rsi
leaq 0x370(%rsp), %rdi
leaq 0x398(%rsp), %rdx
callq 0x6c260
movq $0x0, 0x368(%rsp)
movq $0x0, 0x360(%rsp)
leaq 0x348(%rsp), %rdi
leaq 0x550657(%rip), %rsi    # 0x5794b0
callq 0x6eb90
movl $0x0, 0x344(%rsp)
movq 0x28(%rsp), %rdi
movl 0x344(%rsp), %eax
movl %eax, 0x24(%rsp)
movq 0x400(%rsp), %rsi
callq 0x36b50
movl %eax, %ecx
movl 0x24(%rsp), %eax
cmpl %ecx, %eax
jge 0x2918c
movq 0x28(%rsp), %rdi
movq 0x400(%rsp), %rsi
movl 0x344(%rsp), %edx
callq 0x36ec0
movq 0x28(%rsp), %rdi
movq %rax, 0x338(%rsp)
movq 0x400(%rsp), %rsi
movq 0x338(%rsp), %rdx
xorl %ecx, %ecx
callq 0x36fa0
movq 0x28(%rsp), %rdi
movq %rax, 0x330(%rsp)
movq 0x400(%rsp), %rsi
movq 0x338(%rsp), %rdx
xorl %ecx, %ecx
callq 0x37010
movq %rax, 0x328(%rsp)
cmpq $0x0, 0x328(%rsp)
jne 0x28f0d
jmp 0x29176
movq 0x28(%rsp), %rdi
movq 0x328(%rsp), %rsi
movq 0x400(%rsp), %rdx
callq 0x39c40
movq 0x28(%rsp), %rdi
movq %rax, 0x320(%rsp)
movq 0x338(%rsp), %rsi
movq 0x400(%rsp), %rdx
callq 0x36f50
movq 0x28(%rsp), %rdi
movq %rax, 0x318(%rsp)
movq 0x318(%rsp), %rsi
callq 0x13660
movq %rax, 0x310(%rsp)
movq 0x310(%rsp), %rsi
leaq 0x370(%rsp), %rdi
callq 0x86f90
movsd %xmm0, 0x308(%rsp)
movsd 0x308(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x28fd7
jp 0x28fd7
movq 0x310(%rsp), %rsi
leaq 0x348(%rsp), %rdi
callq 0x6f1e0
movq 0x328(%rsp), %rax
movq %rax, 0x368(%rsp)
movq 0x320(%rsp), %rax
movq %rax, 0x360(%rsp)
jmp 0x2918c
movq 0x28(%rsp), %rdi
movq 0x330(%rsp), %rsi
movq 0x400(%rsp), %rdx
callq 0x36f50
movq 0x28(%rsp), %rdi
movq %rax, 0x300(%rsp)
movq 0x300(%rsp), %rsi
callq 0x13660
movq %rax, 0x2f8(%rsp)
movq 0x2f8(%rsp), %rsi
leaq 0x370(%rsp), %rdi
callq 0x86f90
movsd %xmm0, 0x2f0(%rsp)
movsd 0x2f0(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x2907f
jp 0x2907f
movq 0x2f8(%rsp), %rsi
leaq 0x348(%rsp), %rdi
callq 0x6f1e0
movq 0x328(%rsp), %rax
movq %rax, 0x368(%rsp)
movq 0x320(%rsp), %rax
movq %rax, 0x360(%rsp)
jmp 0x2918c
movsd 0x308(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x29174
xorps %xmm0, %xmm0
ucomisd 0x2f0(%rsp), %xmm0
jbe 0x29174
movsd 0x308(%rsp), %xmm0
movsd 0x308(%rsp), %xmm1
subsd 0x2f0(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x2e8(%rsp)
movq 0x310(%rsp), %rax
movq %rax, 0x18(%rsp)
movsd 0x2e8(%rsp), %xmm0
movsd %xmm0, 0x10(%rsp)
movq 0x2f8(%rsp), %rsi
movq 0x310(%rsp), %rdx
leaq 0x2a0(%rsp), %rdi
callq 0x6eeb0
movsd 0x10(%rsp), %xmm0
leaq 0x2b8(%rsp), %rdi
leaq 0x2a0(%rsp), %rsi
callq 0x13800
movq 0x18(%rsp), %rsi
leaq 0x2d0(%rsp), %rdi
leaq 0x2b8(%rsp), %rdx
callq 0x6f110
leaq 0x348(%rsp), %rdi
leaq 0x2d0(%rsp), %rsi
callq 0x6f1e0
movq 0x328(%rsp), %rax
movq %rax, 0x368(%rsp)
movq 0x320(%rsp), %rax
movq %rax, 0x360(%rsp)
jmp 0x2918c
jmp 0x29176
movl 0x344(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x344(%rsp)
jmp 0x28e69
movq 0x3c8(%rsp), %rsi
leaq 0x348(%rsp), %rdi
callq 0x86c40
movsd %xmm0, 0x298(%rsp)
movq 0x3c8(%rsp), %rdx
leaq 0x280(%rsp), %rdi
leaq 0x348(%rsp), %rsi
callq 0x6eeb0
leaq 0x280(%rsp), %rdi
callq 0x70410
cmpq $0x0, 0x368(%rsp)
jne 0x291f0
xorps %xmm0, %xmm0
movsd %xmm0, 0x410(%rsp)
jmp 0x298d4
movsd 0x298(%rsp), %xmm0
ucomisd 0x3f0(%rsp), %xmm0
jb 0x292d9
movsd 0x3f0(%rsp), %xmm0
divsd 0x298(%rsp), %xmm0
movsd %xmm0, 0x278(%rsp)
cmpq $0x0, 0x3e8(%rsp)
je 0x292a4
movsd 0x109dd2(%rip), %xmm0   # 0x133008
subsd 0x278(%rsp), %xmm0
movq 0x3c8(%rsp), %rsi
leaq 0x248(%rsp), %rdi
callq 0x36b10
movsd 0x278(%rsp), %xmm0
leaq 0x230(%rsp), %rdi
leaq 0x348(%rsp), %rsi
callq 0x36b10
leaq 0x260(%rsp), %rdi
leaq 0x248(%rsp), %rsi
leaq 0x230(%rsp), %rdx
callq 0x6fa40
movq 0x3e8(%rsp), %rdi
leaq 0x260(%rsp), %rsi
callq 0x6f1e0
cmpq $0x0, 0x3e0(%rsp)
je 0x292c2
movq 0x368(%rsp), %rcx
movq 0x3e0(%rsp), %rax
movq %rcx, (%rax)
movsd 0x3f0(%rsp), %xmm0
movsd %xmm0, 0x410(%rsp)
jmp 0x298d4
jmp 0x292db
movq 0x3d0(%rsp), %rdi
movq 0x360(%rsp), %rsi
movl 0x14622f(%rip), %edx    # 0x16f520
callq 0x37c00
movq 0x3d0(%rsp), %rdi
movq 0x368(%rsp), %rsi
movl 0x146214(%rip), %edx    # 0x16f520
callq 0x374e0
cmpq $0x0, 0x3d8(%rsp)
je 0x2941f
cmpq $0x0, 0x420(%rsp)
je 0x2941f
movq 0x3d8(%rsp), %rax
movq 0x420(%rsp), %rcx
movslq (%rcx), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movl $0x2, (%rax)
movq 0x3d8(%rsp), %rax
movq 0x420(%rsp), %rcx
movslq (%rcx), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq $0x0, 0x8(%rax)
movq 0x360(%rsp), %rcx
movq 0x3d8(%rsp), %rax
movq 0x420(%rsp), %rdx
movslq (%rdx), %rdx
shlq $0x6, %rdx
addq %rdx, %rax
movq %rcx, 0x10(%rax)
movq 0x368(%rsp), %rcx
movq 0x3d8(%rsp), %rax
movq 0x420(%rsp), %rdx
movslq (%rdx), %rdx
shlq $0x6, %rdx
addq %rdx, %rax
movq %rcx, 0x18(%rax)
movq 0x3d8(%rsp), %rdi
movq 0x420(%rsp), %rax
movslq (%rax), %rax
shlq $0x6, %rax
addq %rax, %rdi
addq $0x20, %rdi
leaq 0x348(%rsp), %rsi
callq 0x6f1e0
movsd 0x298(%rsp), %xmm0
movq 0x3d8(%rsp), %rax
movq 0x420(%rsp), %rcx
movslq (%rcx), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movsd %xmm0, 0x38(%rax)
movq 0x420(%rsp), %rax
movl (%rax), %ecx
addl $0x1, %ecx
movl %ecx, (%rax)
movq 0x28(%rsp), %rdi
movq 0x360(%rsp), %rsi
movq 0x368(%rsp), %rdx
callq 0x373c0
movq %rax, 0x228(%rsp)
cmpq $0x0, 0x228(%rsp)
jne 0x294a1
cmpq $0x0, 0x3e8(%rsp)
je 0x2946c
movq 0x3e8(%rsp), %rdi
leaq 0x348(%rsp), %rsi
callq 0x6f1e0
cmpq $0x0, 0x3e0(%rsp)
je 0x2948a
movq 0x368(%rsp), %rcx
movq 0x3e0(%rsp), %rax
movq %rcx, (%rax)
movsd 0x298(%rsp), %xmm0
movsd %xmm0, 0x410(%rsp)
jmp 0x298d4
movq 0x28(%rsp), %rdi
movq 0x368(%rsp), %rsi
callq 0x13840
movq %rax, %rsi
leaq 0x210(%rsp), %rdi
callq 0x6fcf0
movq 0x28(%rsp), %rdi
movq 0x228(%rsp), %rsi
callq 0x13840
movq %rax, %rsi
leaq 0x1f8(%rsp), %rdi
callq 0x6fcf0
leaq 0x178(%rsp), %rdi
leaq 0x14f73c(%rip), %rsi    # 0x178c30
callq 0x51b60
leaq 0x178(%rsp), %rdi
leaq 0x210(%rsp), %rsi
leaq 0x1f8(%rsp), %rdx
callq 0x53ec0
leaq 0x160(%rsp), %rdi
leaq 0x178(%rsp), %rsi
leaq 0x280(%rsp), %rdx
callq 0x54fe0
leaq 0x160(%rsp), %rdi
callq 0x70410
leaq 0x148(%rsp), %rdi
leaq 0x1f8(%rsp), %rsi
leaq 0x160(%rsp), %rdx
callq 0x70af0
leaq 0x148(%rsp), %rdi
callq 0x70410
leaq 0x128(%rsp), %rdi
leaq 0x348(%rsp), %rsi
leaq 0x148(%rsp), %rdx
callq 0x6c260
movq 0x28(%rsp), %rdi
movq 0x228(%rsp), %rsi
movq 0x360(%rsp), %rdx
callq 0x37070
movq 0x28(%rsp), %rdi
movq %rax, 0x120(%rsp)
movq 0x120(%rsp), %rsi
callq 0x13660
movq %rax, %rsi
leaq 0x108(%rsp), %rdi
callq 0x6eb90
leaq 0x128(%rsp), %rdi
leaq 0x108(%rsp), %rsi
callq 0x86f90
movq 0x28(%rsp), %rdi
movsd %xmm0, 0x100(%rsp)
movq 0x228(%rsp), %rsi
movq 0x360(%rsp), %rdx
movsd 0x100(%rsp), %xmm1
xorps %xmm0, %xmm0
xorl %ecx, %ecx
movl $0x1, %eax
ucomisd %xmm1, %xmm0
cmoval %eax, %ecx
callq 0x386a0
movq %rax, 0xf8(%rsp)
movsd 0x100(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x2963e
jp 0x2963e
jmp 0x29758
movq 0x28(%rsp), %rsi
movq 0xf8(%rsp), %rdx
leaq 0xe0(%rsp), %rdi
callq 0x37120
leaq 0x128(%rsp), %rdi
callq 0x13e60
movq %rax, %rdi
leaq 0xe0(%rsp), %rsi
callq 0x702c0
movsd %xmm0, 0xd8(%rsp)
movsd 0xd8(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x29697
jp 0x29697
jmp 0x29756
movq 0x28(%rsp), %rdi
movq 0xf8(%rsp), %rsi
xorl %edx, %edx
callq 0x36960
movq 0x28(%rsp), %rdi
movq %rax, %rsi
callq 0x13660
movq %rax, %rsi
leaq 0xc0(%rsp), %rdi
callq 0x6eb90
leaq 0x128(%rsp), %rdi
leaq 0xc0(%rsp), %rsi
callq 0x86f90
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
divsd 0xd8(%rsp), %xmm0
movsd %xmm0, 0xb8(%rsp)
movsd 0xb8(%rsp), %xmm0
leaq 0x88(%rsp), %rdi
leaq 0xe0(%rsp), %rsi
callq 0x70b80
leaq 0xa0(%rsp), %rdi
leaq 0xc0(%rsp), %rsi
leaq 0x88(%rsp), %rdx
callq 0x6f110
leaq 0x108(%rsp), %rdi
leaq 0xa0(%rsp), %rsi
callq 0x6f1e0
jmp 0x29758
movsd 0x298(%rsp), %xmm0
movsd %xmm0, 0x8(%rsp)
leaq 0x348(%rsp), %rdi
leaq 0x108(%rsp), %rsi
callq 0x86c40
movaps %xmm0, %xmm1
movsd 0x8(%rsp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x80(%rsp)
movsd 0x80(%rsp), %xmm0
ucomisd 0x3f0(%rsp), %xmm0
jb 0x29873
movsd 0x3f0(%rsp), %xmm0
subsd 0x298(%rsp), %xmm0
movsd 0x80(%rsp), %xmm1
subsd 0x298(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x78(%rsp)
cmpq $0x0, 0x3e8(%rsp)
je 0x29841
movsd 0x10981d(%rip), %xmm0   # 0x133008
subsd 0x78(%rsp), %xmm0
leaq 0x48(%rsp), %rdi
leaq 0x348(%rsp), %rsi
callq 0x36b10
movsd 0x78(%rsp), %xmm0
leaq 0x30(%rsp), %rdi
leaq 0x108(%rsp), %rsi
callq 0x36b10
leaq 0x60(%rsp), %rdi
leaq 0x48(%rsp), %rsi
leaq 0x30(%rsp), %rdx
callq 0x6fa40
movq 0x3e8(%rsp), %rdi
leaq 0x60(%rsp), %rsi
callq 0x6f1e0
cmpq $0x0, 0x3e0(%rsp)
je 0x2985f
movq 0x228(%rsp), %rcx
movq 0x3e0(%rsp), %rax
movq %rcx, (%rax)
movsd 0x3f0(%rsp), %xmm0
movsd %xmm0, 0x410(%rsp)
jmp 0x298d4
movq 0xf8(%rsp), %rax
movq %rax, 0x360(%rsp)
movq 0x228(%rsp), %rax
movq %rax, 0x368(%rsp)
leaq 0x348(%rsp), %rdi
leaq 0x108(%rsp), %rsi
callq 0x6f1e0
leaq 0x280(%rsp), %rdi
leaq 0x160(%rsp), %rsi
callq 0x70970
movsd 0x80(%rsp), %xmm0
movsd %xmm0, 0x298(%rsp)
jmp 0x292db
movsd 0x410(%rsp), %xmm0
addq $0x418, %rsp            # imm = 0x418
retq
nopw %cs:(%rax,%rax)