// File: tomfunkhouser[P]gaps/apps/msh2pts/msh2pts.cpp
// Function: SelectExteriorSurfacePoints(gaps::R3Mesh*, int, double)
static RNArray<Point *> *
SelectExteriorSurfacePoints(R3Mesh *mesh, int npoints, double min_spacing)
{
  // Allocate array of points
  RNArray<Point *> *points = new RNArray<Point *>();
  if (!points) {
    RNFail("Unable to allocate array of points\n");
    return NULL;
  }

  // Initialize grid
  RNArea area_per_point = mesh->Area() / npoints;
  RNScalar grid_spacing = sqrt(area_per_point);
  if (grid_spacing < min_spacing) grid_spacing = min_spacing;
  R3Grid exterior_grid(mesh->BBox(), grid_spacing, 5, 1024, 2);
  const RNScalar *exterior_grid_values = exterior_grid.GridValues();
  grid_spacing = exterior_grid.GridToWorldScaleFactor();

  // Initialize mesh search tree
  R3MeshSearchTree search_tree(mesh);

  // Initialze point search tree
  Point tmp; int position_offset = (unsigned char *) &(tmp.position) - (unsigned char *) &tmp;
  R3Kdtree<Point *> kdtree(exterior_grid.WorldBox(), position_offset);

  // Seed search with border voxels (assumed outside)
  int ix, iy, iz, grid_index;
  RNArray<const RNScalar *> stack;
  for (int i = 0; i < exterior_grid.XResolution(); i++) {
    for (int j = 0; j < exterior_grid.YResolution(); j++) {
      for (int k = 0; k < exterior_grid.ZResolution(); k++) {
        if ((i == 0) || (i == exterior_grid.XResolution()-1) ||
            (j == 0) || (j == exterior_grid.YResolution()-1) ||
            (k == 0) || (k == exterior_grid.ZResolution()-1)) {
          exterior_grid.IndicesToIndex(i, j, k, grid_index);
          stack.Insert(&exterior_grid_values[grid_index]);
          exterior_grid.SetGridValue(grid_index, 1.0);
        }
      }
    }
  }

  // Flood fill
  while (!stack.IsEmpty()) {
    const RNScalar *exterior_grid_valuep = stack.Tail(); stack.RemoveTail();
    int grid_index = exterior_grid_valuep - exterior_grid_values;
    assert((grid_index >= 0) && (grid_index < exterior_grid.NEntries()));
    assert(exterior_grid.GridValue(grid_index) > 0.5);
    exterior_grid.IndexToIndices(grid_index, ix, iy, iz);
    R3Point p0 = exterior_grid.WorldPosition(ix, iy, iz);
    for (int dz = -1; dz <= 1; dz++) {
      int gz = iz + dz;
      if ((gz < 0) || (gz >= exterior_grid.ZResolution())) continue;
      for (int dy = -1; dy <= 1; dy++) {
        int gy = iy + dy;
        if ((gy < 0) || (gy >= exterior_grid.YResolution())) continue;
        for (int dx = -1; dx <= 1; dx++) {
          int gx = ix + dx;
          if ((gx < 0) || (gx >= exterior_grid.XResolution())) continue;
          if (exterior_grid.GridValue(gx, gy, gz) > 0.5) continue;

#if 1       
          // Create point sample at front-most surface boundary separating cell from its neighbors
          RNBoolean blocked = FALSE;
          R3Point p1 = exterior_grid.WorldPosition(gx, gy, gz);
          R3Ray ray(p0, p1);
          R3Point midpoint = 0.5*(p0 + p1);
          RNArray<R3MeshIntersection *> hits;
          search_tree.FindAll(midpoint, hits, 0, grid_spacing);
          RNScalar best_t = FLT_MAX;
          R3Point best_position = R3zero_point;
          R3Vector best_normal = R3zero_vector;
          for (int k = 0; k < hits.NEntries(); k++) {
            R3MeshIntersection *hit = hits.Kth(k);
            R3Plane plane = mesh->FacePlane(hit->face);
            RNScalar d0 = R3SignedDistance(plane, p0);
            RNScalar d1 = R3SignedDistance(plane, p1);
            if (RNIsNegativeOrZero(d0*d1)) {
              if (mesh->Intersection(ray, hit->face, hit)) {
                if (hit->t < best_t) {
                  best_position = hit->point;
                  best_normal = plane.Normal();
                  if (d0 < 0) best_normal.Flip();
                  best_t = hit->t;
                }
              }
            }
            delete hit;
          }
          if (best_t < FLT_MAX) {
            if ((min_spacing == 0) || !kdtree.FindAny(best_position, 0, min_spacing)) {
              Point *point = new Point(best_position, best_normal);
              kdtree.InsertPoint(point);
              points->Insert(point);
            }
            blocked = TRUE;
          }
#else
          // FOR SOME REASON, THIS DOES NOT WORK
          // Create point sample at front-most surface boundary separating cell from its neighbors
          RNBoolean blocked = FALSE;
          R3Point p1 = exterior_grid.WorldPosition(gx, gy, gz);
          R3Ray ray(p0, p1);
          R3MeshIntersection hit;
          search_tree.FindIntersection(ray, hit, 0, grid_spacing);
          if (hit.type != R3_MESH_NULL_TYPE) {
            if ((min_spacing == 0) || !kdtree.FindAny(hit.point, 0, min_spacing)) {
              R3Point p = hit.point;
              R3Vector n = mesh->FaceNormal(hit.face);
              if (n.Dot(ray.Vector()) > 0) n.Flip();
              Point *point = new Point(p, n);
              kdtree.InsertPoint(point);
              points->Insert(point);
            }
            blocked = TRUE;
          }
#endif
          
          // Continue DFS 
          if (!blocked) {
            exterior_grid.IndicesToIndex(gx, gy, gz, grid_index);
            stack.Insert(&exterior_grid_values[grid_index]);
            exterior_grid.SetGridValue(grid_index, 1.0);
          }
        }
      }
    }
  }

  // exterior_grid.WriteFile("exterior.grd");

  // Return points
  return points;
}

// Assembly:
subq $0x5f8, %rsp            # imm = 0x5F8
movq %rdi, 0x5e8(%rsp)
movl %esi, 0x5e4(%rsp)
movsd %xmm0, 0x5d8(%rsp)
movl $0x10, %edi
callq 0xf4d0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0xd0(%rsp)
callq 0x1b5a0
jmp 0x1541e
movq 0xd0(%rsp), %rax
movq %rax, 0x5d0(%rsp)
cmpq $0x0, 0x5d0(%rsp)
jne 0x15483
leaq 0x1351cf(%rip), %rdi    # 0x14a60f
movb $0x0, %al
callq 0xebe00
movq $0x0, 0x5f0(%rsp)
jmp 0x160f9
movq 0xd0(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x5c8(%rsp)
movl %eax, 0x5c4(%rsp)
movl $0x10, %esi
callq 0xf4e0
jmp 0x16109
movq 0x5e8(%rsp), %rdi
callq 0x41930
cvtsi2sdl 0x5e4(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x5b8(%rsp)
movsd 0x5b8(%rsp), %xmm0
callq 0xf390
movsd %xmm0, 0x5b0(%rsp)
movsd 0x5b0(%rsp), %xmm1
movsd 0x5d8(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x154e7
movsd 0x5d8(%rsp), %xmm0
movsd %xmm0, 0x5b0(%rsp)
movq 0x5e8(%rsp), %rdi
callq 0x1ba30
movq %rax, %rsi
movsd 0x5b0(%rsp), %xmm0
leaq 0x360(%rsp), %rdi
movq %rdi, 0xc0(%rsp)
movl $0x5, %edx
movl $0x400, %ecx            # imm = 0x400
movl $0x2, %r8d
callq 0x83ea0
movq 0xc0(%rsp), %rdi
callq 0x1ba50
movq %rax, 0xc8(%rsp)
jmp 0x1553c
movq 0xc8(%rsp), %rax
movq %rax, 0x358(%rsp)
leaq 0x360(%rsp), %rdi
callq 0x1ba70
movsd %xmm0, 0xb8(%rsp)
jmp 0x15564
movsd 0xb8(%rsp), %xmm0
movsd %xmm0, 0x5b0(%rsp)
movq 0x5e8(%rsp), %rsi
leaq 0x340(%rsp), %rdi
callq 0x1f840
jmp 0x1558d
leaq 0x2f8(%rsp), %rdi
callq 0x1ba90
jmp 0x1559c
movl $0x10, 0x2f4(%rsp)
leaq 0x258(%rsp), %rdi
leaq 0x360(%rsp), %rsi
callq 0x1baf0
jmp 0x155be
movl 0x2f4(%rsp), %edx
leaq 0x290(%rsp), %rdi
leaq 0x258(%rsp), %rsi
callq 0x1bbb0
jmp 0x155dc
leaq 0x258(%rsp), %rdi
callq 0x1b2c0
leaq 0x238(%rsp), %rdi
callq 0x1bc80
jmp 0x155f8
movl $0x0, 0x234(%rsp)
movl 0x234(%rsp), %eax
movl %eax, 0xb0(%rsp)
leaq 0x360(%rsp), %rdi
callq 0x1bc90
movl %eax, 0xb4(%rsp)
jmp 0x15627
movl 0xb0(%rsp), %eax
movl 0xb4(%rsp), %ecx
cmpl %ecx, %eax
jge 0x158e4
movl $0x0, 0x230(%rsp)
movl 0x230(%rsp), %eax
movl %eax, 0xa8(%rsp)
leaq 0x360(%rsp), %rdi
callq 0x1bcb0
movl %eax, 0xac(%rsp)
jmp 0x1566c
movl 0xa8(%rsp), %eax
movl 0xac(%rsp), %ecx
cmpl %ecx, %eax
jge 0x158cc
movl $0x0, 0x22c(%rsp)
movl 0x22c(%rsp), %eax
movl %eax, 0xa0(%rsp)
leaq 0x360(%rsp), %rdi
callq 0x1bcd0
movl %eax, 0xa4(%rsp)
jmp 0x156b1
movl 0xa0(%rsp), %eax
movl 0xa4(%rsp), %ecx
cmpl %ecx, %eax
jge 0x158b4
cmpl $0x0, 0x234(%rsp)
je 0x157a0
movl 0x234(%rsp), %eax
movl %eax, 0x98(%rsp)
leaq 0x360(%rsp), %rdi
callq 0x1bc90
movl %eax, 0x9c(%rsp)
jmp 0x156f9
movl 0x98(%rsp), %eax
movl 0x9c(%rsp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
je 0x157a0
cmpl $0x0, 0x230(%rsp)
je 0x157a0
movl 0x230(%rsp), %eax
movl %eax, 0x90(%rsp)
leaq 0x360(%rsp), %rdi
callq 0x1bcb0
movl %eax, 0x94(%rsp)
jmp 0x15744
movl 0x90(%rsp), %eax
movl 0x94(%rsp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
je 0x157a0
cmpl $0x0, 0x22c(%rsp)
je 0x157a0
movl 0x22c(%rsp), %eax
movl %eax, 0x88(%rsp)
leaq 0x360(%rsp), %rdi
callq 0x1bcd0
movl %eax, 0x8c(%rsp)
jmp 0x15787
movl 0x88(%rsp), %eax
movl 0x8c(%rsp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jne 0x1589c
movl 0x234(%rsp), %esi
movl 0x230(%rsp), %edx
movl 0x22c(%rsp), %ecx
leaq 0x360(%rsp), %rdi
leaq 0x248(%rsp), %r8
callq 0x1bcf0
jmp 0x157cc
movq 0x358(%rsp), %rax
movslq 0x248(%rsp), %rcx
leaq (%rax,%rcx,8), %rsi
leaq 0x238(%rsp), %rdi
callq 0x1bd30
jmp 0x157ef
movl 0x248(%rsp), %esi
leaq 0x360(%rsp), %rdi
movsd 0x13481a(%rip), %xmm0   # 0x14a020
callq 0x1bd60
jmp 0x1580d
jmp 0x1589c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x5c8(%rsp)
movl %eax, 0x5c4(%rsp)
jmp 0x160ea
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x5c8(%rsp)
movl %eax, 0x5c4(%rsp)
jmp 0x160dd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x5c8(%rsp)
movl %eax, 0x5c4(%rsp)
leaq 0x258(%rsp), %rdi
callq 0x1b2c0
jmp 0x160dd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x5c8(%rsp)
movl %eax, 0x5c4(%rsp)
jmp 0x160d0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x5c8(%rsp)
movl %eax, 0x5c4(%rsp)
jmp 0x160c3
jmp 0x1589e
movl 0x22c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x22c(%rsp)
jmp 0x1568d
jmp 0x158b6
movl 0x230(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x230(%rsp)
jmp 0x15648
jmp 0x158ce
movl 0x234(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x234(%rsp)
jmp 0x15603
jmp 0x158e6
leaq 0x238(%rsp), %rdi
callq 0x1bd90
movl %eax, 0x84(%rsp)
jmp 0x158fc
movl 0x84(%rsp), %eax
cmpl $0x0, %eax
setne %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x15914
jmp 0x1607d
leaq 0x238(%rsp), %rdi
callq 0x1bdb0
movq %rax, 0x78(%rsp)
jmp 0x15928
movq 0x78(%rsp), %rax
movq %rax, 0x220(%rsp)
leaq 0x238(%rsp), %rdi
callq 0x1b580
jmp 0x15944
movq 0x220(%rsp), %rax
movq 0x358(%rsp), %rcx
subq %rcx, %rax
shrq $0x3, %rax
movl %eax, 0x21c(%rsp)
movl 0x21c(%rsp), %esi
leaq 0x360(%rsp), %rdi
leaq 0x254(%rsp), %rdx
leaq 0x250(%rsp), %rcx
leaq 0x24c(%rsp), %r8
callq 0x1bdc0
jmp 0x15990
cvtsi2sdl 0x254(%rsp), %xmm0
cvtsi2sdl 0x250(%rsp), %xmm1
cvtsi2sdl 0x24c(%rsp), %xmm2
leaq 0x200(%rsp), %rdi
leaq 0x360(%rsp), %rsi
callq 0x90d40
jmp 0x159c2
movl $0xffffffff, 0x1fc(%rsp) # imm = 0xFFFFFFFF
cmpl $0x1, 0x1fc(%rsp)
jg 0x16078
movl 0x24c(%rsp), %eax
addl 0x1fc(%rsp), %eax
movl %eax, 0x1f8(%rsp)
cmpl $0x0, 0x1f8(%rsp)
jl 0x15a24
movl 0x1f8(%rsp), %eax
movl %eax, 0x70(%rsp)
leaq 0x360(%rsp), %rdi
callq 0x1bcd0
movl %eax, 0x74(%rsp)
jmp 0x15a18
movl 0x70(%rsp), %eax
movl 0x74(%rsp), %ecx
cmpl %ecx, %eax
jl 0x15a29
jmp 0x16062
movl $0xffffffff, 0x1f4(%rsp) # imm = 0xFFFFFFFF
cmpl $0x1, 0x1f4(%rsp)
jg 0x16060
movl 0x250(%rsp), %eax
addl 0x1f4(%rsp), %eax
movl %eax, 0x1f0(%rsp)
cmpl $0x0, 0x1f0(%rsp)
jl 0x15a8b
movl 0x1f0(%rsp), %eax
movl %eax, 0x68(%rsp)
leaq 0x360(%rsp), %rdi
callq 0x1bcb0
movl %eax, 0x6c(%rsp)
jmp 0x15a7f
movl 0x68(%rsp), %eax
movl 0x6c(%rsp), %ecx
cmpl %ecx, %eax
jl 0x15a90
jmp 0x1604a
movl $0xffffffff, 0x1ec(%rsp) # imm = 0xFFFFFFFF
cmpl $0x1, 0x1ec(%rsp)
jg 0x16048
movl 0x254(%rsp), %eax
addl 0x1ec(%rsp), %eax
movl %eax, 0x1e8(%rsp)
cmpl $0x0, 0x1e8(%rsp)
jl 0x15af2
movl 0x1e8(%rsp), %eax
movl %eax, 0x60(%rsp)
leaq 0x360(%rsp), %rdi
callq 0x1bc90
movl %eax, 0x64(%rsp)
jmp 0x15ae6
movl 0x60(%rsp), %eax
movl 0x64(%rsp), %ecx
cmpl %ecx, %eax
jl 0x15af7
jmp 0x16023
movl 0x1e8(%rsp), %esi
movl 0x1f0(%rsp), %edx
movl 0x1f8(%rsp), %ecx
leaq 0x360(%rsp), %rdi
callq 0x1be30
movsd %xmm0, 0x58(%rsp)
jmp 0x15b21
movsd 0x58(%rsp), %xmm0
movsd 0x1344f9(%rip), %xmm1   # 0x14a028
ucomisd %xmm1, %xmm0
jbe 0x15b3a
jmp 0x16023
movl $0x0, 0x1e4(%rsp)
cvtsi2sdl 0x1e8(%rsp), %xmm0
cvtsi2sdl 0x1f0(%rsp), %xmm1
cvtsi2sdl 0x1f8(%rsp), %xmm2
leaq 0x1c8(%rsp), %rdi
leaq 0x360(%rsp), %rsi
callq 0x90d40
jmp 0x15b77
leaq 0x198(%rsp), %rdi
leaq 0x200(%rsp), %rsi
leaq 0x1c8(%rsp), %rdx
callq 0x9c590
jmp 0x15b96
leaq 0x168(%rsp), %rdi
leaq 0x200(%rsp), %rsi
leaq 0x1c8(%rsp), %rdx
callq 0x9db50
jmp 0x15bb5
leaq 0x180(%rsp), %rdi
movsd 0x134463(%rip), %xmm0   # 0x14a028
leaq 0x168(%rsp), %rsi
callq 0x1b8b0
jmp 0x15bd4
leaq 0x158(%rsp), %rdi
callq 0x1be80
jmp 0x15be3
movsd 0x5b0(%rsp), %xmm1
xorl %eax, %eax
movl %eax, %r8d
leaq 0x340(%rsp), %rdi
leaq 0x180(%rsp), %rsi
leaq 0x158(%rsp), %rdx
xorps %xmm0, %xmm0
movq %r8, %rcx
callq 0x24770
jmp 0x15c16
movabsq $0x47efffffe0000000, %rax # imm = 0x47EFFFFFE0000000
movq %rax, 0x150(%rsp)
leaq 0x57cb81(%rip), %rsi    # 0x5927b0
leaq 0x138(%rsp), %rdi
callq 0x9cca0
jmp 0x15c3e
leaq 0x57cc5b(%rip), %rsi    # 0x5928a0
leaq 0x120(%rsp), %rdi
callq 0x9de00
jmp 0x15c54
movl $0x0, 0x11c(%rsp)
movl 0x11c(%rsp), %eax
movl %eax, 0x54(%rsp)
leaq 0x158(%rsp), %rdi
callq 0x1b2f0
movl %eax, %ecx
movl 0x54(%rsp), %eax
cmpl %ecx, %eax
jge 0x15e9c
movl 0x11c(%rsp), %esi
leaq 0x158(%rsp), %rdi
callq 0x1be90
movq %rax, 0x48(%rsp)
jmp 0x15ca0
movq 0x48(%rsp), %rax
movq %rax, 0x110(%rsp)
movq 0x5e8(%rsp), %rdi
movq 0x110(%rsp), %rax
movq 0x18(%rax), %rsi
callq 0x1beb0
movq %rax, 0x40(%rsp)
jmp 0x15ccd
movq 0x40(%rsp), %rsi
leaq 0xf0(%rsp), %rdi
callq 0x9a280
jmp 0x15ce1
leaq 0xf0(%rsp), %rdi
leaq 0x200(%rsp), %rsi
callq 0x3a950
movsd %xmm0, 0x38(%rsp)
jmp 0x15cfe
movsd 0x38(%rsp), %xmm0
movsd %xmm0, 0xe8(%rsp)
leaq 0xf0(%rsp), %rdi
leaq 0x1c8(%rsp), %rsi
callq 0x3a950
movsd %xmm0, 0x30(%rsp)
jmp 0x15d2a
movsd 0x30(%rsp), %xmm0
movsd %xmm0, 0xe0(%rsp)
movsd 0xe8(%rsp), %xmm0
movsd 0xe0(%rsp), %xmm1
mulsd %xmm1, %xmm0
leaq 0x17b7ba(%rip), %rax    # 0x191510
movsd (%rax), %xmm1
callq 0x1bf20
movl %eax, 0x2c(%rsp)
jmp 0x15d65
movl 0x2c(%rsp), %eax
cmpl $0x0, %eax
je 0x15e62
movq 0x5e8(%rsp), %rdi
movq 0x110(%rsp), %rcx
movq 0x18(%rcx), %rdx
movq (%rdi), %rax
movq 0x178(%rax), %rax
leaq 0x198(%rsp), %rsi
callq *%rax
movl %eax, 0x28(%rsp)
jmp 0x15da0
movl 0x28(%rsp), %eax
cmpl $0x0, %eax
je 0x15e60
movq 0x110(%rsp), %rax
movsd 0x38(%rax), %xmm1
movsd 0x150(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x15e5e
movq 0x110(%rsp), %rsi
addq $0x20, %rsi
leaq 0x138(%rsp), %rdi
callq 0x9d2f0
jmp 0x15de8
leaq 0xf0(%rsp), %rdi
callq 0x1bf50
movq %rax, 0x20(%rsp)
jmp 0x15dfc
movq 0x20(%rsp), %rsi
leaq 0x120(%rsp), %rdi
callq 0x9ea80
jmp 0x15e10
xorps %xmm0, %xmm0
ucomisd 0xe8(%rsp), %xmm0
jbe 0x15e48
leaq 0x120(%rsp), %rdi
callq 0x9e5a0
jmp 0x15e2d
jmp 0x15e48
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x5c8(%rsp)
movl %eax, 0x5c4(%rsp)
jmp 0x16039
movq 0x110(%rsp), %rax
movsd 0x38(%rax), %xmm0
movsd %xmm0, 0x150(%rsp)
jmp 0x15e60
jmp 0x15e62
movq 0x110(%rsp), %rax
movq %rax, 0x18(%rsp)
cmpq $0x0, %rax
je 0x15e84
movq 0x18(%rsp), %rdi
movl $0x40, %esi
callq 0xf4e0
jmp 0x15e86
movl 0x11c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x11c(%rsp)
jmp 0x15c5f
movsd 0x134164(%rip), %xmm0   # 0x14a008
ucomisd 0x150(%rsp), %xmm0
jbe 0x15f9d
movsd 0x5d8(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x15ec9
jp 0x15ec9
jmp 0x15f00
movsd 0x5d8(%rsp), %xmm1
leaq 0x290(%rsp), %rdi
leaq 0x138(%rsp), %rsi
xorps %xmm0, %xmm0
callq 0x1bf60
movq %rax, 0x10(%rsp)
jmp 0x15ef1
movq 0x10(%rsp), %rax
cmpq $0x0, %rax
jne 0x15f92
movl $0x48, %edi
callq 0xf4d0
movq %rax, 0x8(%rsp)
jmp 0x15f11
movq 0x8(%rsp), %rdi
leaq 0x138(%rsp), %rsi
leaq 0x120(%rsp), %rdx
callq 0x1b4e0
jmp 0x15f2d
movq 0x8(%rsp), %rax
movq %rax, 0xd8(%rsp)
movq 0xd8(%rsp), %rsi
leaq 0x290(%rsp), %rdi
callq 0x1c030
jmp 0x15f51
movq 0x5d0(%rsp), %rdi
movq 0xd8(%rsp), %rsi
callq 0x1b540
jmp 0x15f68
jmp 0x15f92
movq 0x8(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x5c8(%rsp)
movl %eax, 0x5c4(%rsp)
movl $0x48, %esi
callq 0xf4e0
jmp 0x16039
movl $0x1, 0x1e4(%rsp)
cmpl $0x0, 0x1e4(%rsp)
jne 0x16016
movl 0x1e8(%rsp), %esi
movl 0x1f0(%rsp), %edx
movl 0x1f8(%rsp), %ecx
leaq 0x360(%rsp), %rdi
leaq 0x21c(%rsp), %r8
callq 0x1bcf0
jmp 0x15fd3
movq 0x358(%rsp), %rax
movslq 0x21c(%rsp), %rcx
leaq (%rax,%rcx,8), %rsi
leaq 0x238(%rsp), %rdi
callq 0x1bd30
jmp 0x15ff6
movl 0x21c(%rsp), %esi
leaq 0x360(%rsp), %rdi
movsd 0x134013(%rip), %xmm0   # 0x14a020
callq 0x1bd60
jmp 0x16014
jmp 0x16016
leaq 0x158(%rsp), %rdi
callq 0x1c070
movl 0x1ec(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1ec(%rsp)
jmp 0x15a9b
leaq 0x158(%rsp), %rdi
callq 0x1c070
jmp 0x160c3
jmp 0x1604a
movl 0x1f4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1f4(%rsp)
jmp 0x15a34
jmp 0x16062
movl 0x1fc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1fc(%rsp)
jmp 0x159cd
jmp 0x158e6
movq 0x5d0(%rsp), %rax
movq %rax, 0x5f0(%rsp)
leaq 0x238(%rsp), %rdi
callq 0x1c080
leaq 0x290(%rsp), %rdi
callq 0x1c090
leaq 0x340(%rsp), %rdi
callq 0x1fa00
leaq 0x360(%rsp), %rdi
callq 0x849d0
jmp 0x160f9
leaq 0x238(%rsp), %rdi
callq 0x1c080
leaq 0x290(%rsp), %rdi
callq 0x1c090
leaq 0x340(%rsp), %rdi
callq 0x1fa00
leaq 0x360(%rsp), %rdi
callq 0x849d0
jmp 0x16109
movq 0x5f0(%rsp), %rax
addq $0x5f8, %rsp            # imm = 0x5F8
retq
movq 0x5c8(%rsp), %rdi
callq 0xf8a0
nopw %cs:(%rax,%rax)