// File: tomfunkhouser[P]gaps/pkgs/R3Graphics/R3Scene.cpp
// Function: gaps::R3Scene::ReadSUNCGModelFile(char const*)
int R3Scene::
ReadSUNCGModelFile(const char *filename)
{
  // Open file
  FILE *fp = fopen(filename, "r");
  if (!fp) {
    RNFail("Unable to open lights file %s\n", filename);
    return 0;
  }

  // Read keys from first line
  int line_number = 1;
  char key_buffer[4096];
  RNArray<char *> keys;
  if (fgets(key_buffer, 4096, fp)) {
    char *token = strtok(key_buffer, ",\r\n");
    while (token) {
      keys.Insert(RNStrdup(token));
      token = strtok(NULL, ",\r\n");
    }
  }

  // Extract index of model_id
  int model_id_k = -1;
  for (int i = 0; i < keys.NEntries(); i++) {
    if (!strcmp(keys[i], "model_id")) {
      model_id_k = i;
      break;
    }
  }

  // Check if found model_id
  if (model_id_k < 0) {
    RNFail("Did not find \"model_id\" in header on line %d of %s\n", line_number, filename);
    return 0;
  }

  // Read subsequent lines of file
  char value_buffer[4096];
  while (fgets(value_buffer, 4096, fp)) {
    line_number++;

    // Read values
    RNArray<char *> values;
    char *token = strtok(value_buffer, ",\r\n");
    while (token) {
      values.Insert(RNStrdup(token));
      token = strtok(NULL, ",\r\n");
    }

    // Check number of values
    if (values.NEntries() == 0) continue;
    if (values.NEntries() != keys.NEntries()) {
      RNFail("Invalid number of entries at line %d in %s\n", line_number, filename);
      return 0;
    }

    // Get model id
    const char *model_id = values[model_id_k];
    if (!model_id) continue;
    int model_id_length = strlen(model_id);
    if (model_id_length == 0) continue;

    // Assign key-value info to nodes matching model_id
    for (int i = 0; i < NNodes(); i++) {
      R3SceneNode *node = Node(i);

      // Determine if node name matches model_id
      if (node->Name()) {
        char node_name[1024];
        strncpy(node_name, node->Name(), 1023);
        char *model_name = strchr(node_name, '#');
        if (model_name) { *model_name = '\0'; model_name++; }
        else model_name = node_name;
        if (!strcmp(node_name, model_id) || !strcmp(model_name, model_id)) {
          for (int j = 0; j < keys.NEntries(); j++) node->InsertInfo(keys[j], values[j]);
        }
      }

      // Determine if referenced scene name matches model_id
      for (int j = 0; j < node->NReferences(); j++) {
        R3SceneReference *reference = node->Reference(j);
        R3Scene *referenced_scene = reference->ReferencedScene();
        R3SceneNode *root = referenced_scene->Root();
        if (!root->Name()) continue;
        char node_name[1024];
        strncpy(node_name, root->Name(), 1023);
        char *model_name = strchr(node_name, '#');
        if (model_name) { *model_name = '\0'; model_name++; }
        else model_name = node_name;
        if (!strcmp(node_name, model_id) || !strcmp(model_name, model_id)) {
          for (int j = 0; j < keys.NEntries(); j++) node->InsertInfo(keys[j], values[j]);
          break;
        }
      }
    }

    // Assign key-value info to root node of referenced scene matching model_id
    R3Scene *model = ReferencedScene(model_id);
    if (model) {
      for (int i = 0; i < keys.NEntries(); i++) {
        model->Root()->InsertInfo(keys[i], values[i]);
      }
    }
  }

  // Close file
  fclose(fp);

  // Delete inactive nodes
  RNArray<R3SceneNode *> tmp;
  for (int i = 0; i < NNodes(); i++)
    tmp.Insert(Node(i));
  for (int i = 0; i < tmp.NEntries(); i++) {
    R3SceneNode *node = tmp.Kth(i);
    const char *active = node->Info("active");
    if (!active) continue;
    if (strcmp(active, "0")) continue;
    delete node;
  }

  
#if 0
  // Print result
  for (int i = 0; i < NNodes(); i++) {
    R3SceneNode *node = Node(i);
    const char *model_index = node->Info("index");
    if (model_index) printf("%s %s\n", node->Name(), model_index);
  }
#endif
  
  // Return success
  return 1;
}

// Assembly:
subq $0x2a78, %rsp           # imm = 0x2A78
movq %rdi, 0x2a68(%rsp)
movq %rsi, 0x2a60(%rsp)
movq 0x2a68(%rsp), %rax
movq %rax, 0x160(%rsp)
movq 0x2a60(%rsp), %rdi
leaq 0x15323d(%rip), %rsi    # 0x1952a3
callq 0x22c10
movq %rax, 0x2a58(%rsp)
cmpq $0x0, 0x2a58(%rsp)
jne 0x420a4
movq 0x2a60(%rsp), %rsi
leaq 0x14d379(%rip), %rdi    # 0x18f406
movb $0x0, %al
callq 0xf3b00
movl $0x0, 0x2a74(%rsp)
jmp 0x42cae
movl $0x1, 0x2a54(%rsp)
leaq 0x1a40(%rsp), %rdi
callq 0x497d0
movq 0x2a58(%rsp), %rdx
leaq 0x1a50(%rsp), %rdi
movl $0x1000, %esi           # imm = 0x1000
callq 0x230f0
movq %rax, 0x158(%rsp)
jmp 0x420e0
movq 0x158(%rsp), %rax
cmpq $0x0, %rax
je 0x4217c
leaq 0x1a50(%rsp), %rdi
leaq 0x14d4e4(%rip), %rsi    # 0x18f5e5
callq 0x230a0
movq %rax, 0x1a28(%rsp)
cmpq $0x0, 0x1a28(%rsp)
je 0x4217a
movq 0x1a28(%rsp), %rdi
callq 0xf3800
movq %rax, 0x150(%rsp)
jmp 0x42130
movq 0x150(%rsp), %rsi
leaq 0x1a40(%rsp), %rdi
callq 0x497e0
jmp 0x42147
xorl %eax, %eax
movl %eax, %edi
leaq 0x14d493(%rip), %rsi    # 0x18f5e5
callq 0x230a0
movq %rax, 0x1a28(%rsp)
jmp 0x4210e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1a38(%rsp)
movl %eax, 0x1a34(%rsp)
jmp 0x42c9f
jmp 0x4217c
movl $0xffffffff, 0x1a24(%rsp) # imm = 0xFFFFFFFF
movl $0x0, 0x1a20(%rsp)
movl 0x1a20(%rsp), %eax
movl %eax, 0x148(%rsp)
leaq 0x1a40(%rsp), %rdi
callq 0x2b8b0
movl %eax, 0x14c(%rsp)
jmp 0x421b6
movl 0x148(%rsp), %eax
movl 0x14c(%rsp), %ecx
cmpl %ecx, %eax
jge 0x4222a
movl 0x1a20(%rsp), %esi
leaq 0x1a40(%rsp), %rdi
callq 0x49810
movq %rax, 0x140(%rsp)
jmp 0x421e6
movq 0x140(%rsp), %rax
movq (%rax), %rdi
leaq 0x14d3f1(%rip), %rsi    # 0x18f5e9
callq 0x22ec0
cmpl $0x0, %eax
jne 0x42212
movl 0x1a20(%rsp), %eax
movl %eax, 0x1a24(%rsp)
jmp 0x4222a
jmp 0x42214
movl 0x1a20(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1a20(%rsp)
jmp 0x42192
cmpl $0x0, 0x1a24(%rsp)
jge 0x4226e
movl 0x2a54(%rsp), %esi
movq 0x2a60(%rsp), %rdx
leaq 0x14d3a8(%rip), %rdi    # 0x18f5f2
xorl %eax, %eax
callq 0xf3b00
jmp 0x42253
movl $0x0, 0x2a74(%rsp)
movl $0x1, 0x1a1c(%rsp)
jmp 0x42c90
jmp 0x42270
movq 0x2a58(%rsp), %rdx
leaq 0xa10(%rsp), %rdi
movl $0x1000, %esi           # imm = 0x1000
callq 0x230f0
movq %rax, 0x138(%rsp)
jmp 0x42294
movq 0x138(%rsp), %rax
cmpq $0x0, %rax
je 0x42abe
movl 0x2a54(%rsp), %eax
incl %eax
movl %eax, 0x2a54(%rsp)
leaq 0xa00(%rsp), %rdi
callq 0x497d0
jmp 0x422c5
leaq 0xa10(%rsp), %rdi
leaq 0x14d311(%rip), %rsi    # 0x18f5e5
callq 0x230a0
movq %rax, 0x9f8(%rsp)
cmpq $0x0, 0x9f8(%rsp)
je 0x4235a
movq 0x9f8(%rsp), %rdi
callq 0xf3800
movq %rax, 0x130(%rsp)
jmp 0x42303
movq 0x130(%rsp), %rsi
leaq 0xa00(%rsp), %rdi
callq 0x497e0
jmp 0x4231a
xorl %eax, %eax
movl %eax, %edi
leaq 0x14d2c0(%rip), %rsi    # 0x18f5e5
callq 0x230a0
movq %rax, 0x9f8(%rsp)
jmp 0x422e1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1a38(%rsp)
movl %eax, 0x1a34(%rsp)
leaq 0xa00(%rsp), %rdi
callq 0x49830
jmp 0x42c9f
leaq 0xa00(%rsp), %rdi
callq 0x2b8b0
movl %eax, 0x12c(%rsp)
jmp 0x42370
movl 0x12c(%rsp), %eax
cmpl $0x0, %eax
jne 0x4238c
movl $0x7, 0x1a1c(%rsp)
jmp 0x42a89
leaq 0xa00(%rsp), %rdi
callq 0x2b8b0
movl %eax, 0x128(%rsp)
jmp 0x423a2
leaq 0x1a40(%rsp), %rdi
callq 0x2b8b0
movl %eax, 0x124(%rsp)
jmp 0x423b8
movl 0x128(%rsp), %eax
movl 0x124(%rsp), %ecx
cmpl %ecx, %eax
je 0x42404
movl 0x2a54(%rsp), %esi
movq 0x2a60(%rsp), %rdx
leaq 0x14d246(%rip), %rdi    # 0x18f626
xorl %eax, %eax
callq 0xf3b00
jmp 0x423e9
movl $0x0, 0x2a74(%rsp)
movl $0x1, 0x1a1c(%rsp)
jmp 0x42a89
movl 0x1a24(%rsp), %esi
leaq 0xa00(%rsp), %rdi
callq 0x49810
movq %rax, 0x118(%rsp)
jmp 0x42422
movq 0x118(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x9f0(%rsp)
cmpq $0x0, 0x9f0(%rsp)
jne 0x42450
movl $0x7, 0x1a1c(%rsp)
jmp 0x42a89
movq 0x9f0(%rsp), %rdi
callq 0x223d0
movl %eax, 0x9ec(%rsp)
cmpl $0x0, 0x9ec(%rsp)
jne 0x4247e
movl $0x7, 0x1a1c(%rsp)
jmp 0x42a89
movl $0x0, 0x9e8(%rsp)
movq 0x160(%rsp), %rdi
movl 0x9e8(%rsp), %eax
movl %eax, 0x110(%rsp)
callq 0x2bf50
movl %eax, 0x114(%rsp)
jmp 0x424ad
movl 0x110(%rsp), %eax
movl 0x114(%rsp), %ecx
cmpl %ecx, %eax
jge 0x42983
movq 0x160(%rsp), %rdi
movl 0x9e8(%rsp), %esi
callq 0x2bf70
movq %rax, 0x108(%rsp)
jmp 0x424e1
movq 0x108(%rsp), %rax
movq %rax, 0x9e0(%rsp)
movq 0x9e0(%rsp), %rdi
callq 0x2b800
movq %rax, 0x100(%rsp)
jmp 0x42508
movq 0x100(%rsp), %rax
cmpq $0x0, %rax
je 0x426cb
leaq 0x5e0(%rsp), %rax
movq %rax, 0xf0(%rsp)
movq 0x9e0(%rsp), %rdi
callq 0x2b800
movq %rax, 0xf8(%rsp)
jmp 0x42541
movq 0xf8(%rsp), %rsi
movq 0xf0(%rsp), %rdi
movl $0x3ff, %edx            # imm = 0x3FF
callq 0x224b0
leaq 0x5e0(%rsp), %rdi
movl $0x23, %esi
callq 0x22350
movq %rax, 0x5d8(%rsp)
cmpq $0x0, 0x5d8(%rsp)
je 0x425a1
movq 0x5d8(%rsp), %rax
movb $0x0, (%rax)
movq 0x5d8(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x5d8(%rsp)
jmp 0x425b1
leaq 0x5e0(%rsp), %rax
movq %rax, 0x5d8(%rsp)
leaq 0x5e0(%rsp), %rdi
movq 0x9f0(%rsp), %rsi
callq 0x22ec0
cmpl $0x0, %eax
je 0x425e9
movq 0x5d8(%rsp), %rdi
movq 0x9f0(%rsp), %rsi
callq 0x22ec0
cmpl $0x0, %eax
jne 0x426c9
movl $0x0, 0x5d4(%rsp)
movl 0x5d4(%rsp), %eax
movl %eax, 0xe8(%rsp)
leaq 0x1a40(%rsp), %rdi
callq 0x2b8b0
movl %eax, 0xec(%rsp)
jmp 0x42618
movl 0xe8(%rsp), %eax
movl 0xec(%rsp), %ecx
cmpl %ecx, %eax
jge 0x426c7
movq 0x9e0(%rsp), %rax
movq %rax, 0xd8(%rsp)
movl 0x5d4(%rsp), %esi
leaq 0x1a40(%rsp), %rdi
callq 0x49810
movq %rax, 0xe0(%rsp)
jmp 0x4265c
movq 0xe0(%rsp), %rax
movq (%rax), %rax
movq %rax, 0xc8(%rsp)
movl 0x5d4(%rsp), %esi
leaq 0xa00(%rsp), %rdi
callq 0x49810
movq %rax, 0xd0(%rsp)
jmp 0x4268d
movq 0xc8(%rsp), %rsi
movq 0xd8(%rsp), %rdi
movq 0xd0(%rsp), %rax
movq (%rax), %rdx
callq 0x57590
jmp 0x426af
jmp 0x426b1
movl 0x5d4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x5d4(%rsp)
jmp 0x425f4
jmp 0x426c9
jmp 0x426cb
movl $0x0, 0x5d0(%rsp)
movl 0x5d0(%rsp), %eax
movl %eax, 0xc0(%rsp)
movq 0x9e0(%rsp), %rdi
callq 0x2bb40
movl %eax, 0xc4(%rsp)
jmp 0x426fa
movl 0xc0(%rsp), %eax
movl 0xc4(%rsp), %ecx
cmpl %ecx, %eax
jge 0x4296b
movq 0x9e0(%rsp), %rdi
movl 0x5d0(%rsp), %esi
callq 0x2bb60
movq %rax, 0xb8(%rsp)
jmp 0x4272e
movq 0xb8(%rsp), %rax
movq %rax, 0x5c8(%rsp)
movq 0x5c8(%rsp), %rdi
callq 0x2bb90
movq %rax, 0xb0(%rsp)
jmp 0x42755
movq 0xb0(%rsp), %rax
movq %rax, 0x5c0(%rsp)
movq 0x5c0(%rsp), %rdi
callq 0x2b510
movq %rax, 0xa8(%rsp)
jmp 0x4277c
movq 0xa8(%rsp), %rax
movq %rax, 0x5b8(%rsp)
movq 0x5b8(%rsp), %rdi
callq 0x2b800
movq %rax, 0xa0(%rsp)
jmp 0x427a3
movq 0xa0(%rsp), %rax
cmpq $0x0, %rax
jne 0x427b6
jmp 0x42955
leaq 0x1b0(%rsp), %rax
movq %rax, 0x90(%rsp)
movq 0x5b8(%rsp), %rdi
callq 0x2b800
movq %rax, 0x98(%rsp)
jmp 0x427dd
movq 0x98(%rsp), %rsi
movq 0x90(%rsp), %rdi
movl $0x3ff, %edx            # imm = 0x3FF
callq 0x224b0
leaq 0x1b0(%rsp), %rdi
movl $0x23, %esi
callq 0x22350
movq %rax, 0x1a8(%rsp)
cmpq $0x0, 0x1a8(%rsp)
je 0x4283d
movq 0x1a8(%rsp), %rax
movb $0x0, (%rax)
movq 0x1a8(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x1a8(%rsp)
jmp 0x4284d
leaq 0x1b0(%rsp), %rax
movq %rax, 0x1a8(%rsp)
leaq 0x1b0(%rsp), %rdi
movq 0x9f0(%rsp), %rsi
callq 0x22ec0
cmpl $0x0, %eax
je 0x42885
movq 0x1a8(%rsp), %rdi
movq 0x9f0(%rsp), %rsi
callq 0x22ec0
cmpl $0x0, %eax
jne 0x42953
movl $0x0, 0x1a4(%rsp)
movl 0x1a4(%rsp), %eax
movl %eax, 0x88(%rsp)
leaq 0x1a40(%rsp), %rdi
callq 0x2b8b0
movl %eax, 0x8c(%rsp)
jmp 0x428b4
movl 0x88(%rsp), %eax
movl 0x8c(%rsp), %ecx
cmpl %ecx, %eax
jge 0x42951
movq 0x9e0(%rsp), %rax
movq %rax, 0x78(%rsp)
movl 0x1a4(%rsp), %esi
leaq 0x1a40(%rsp), %rdi
callq 0x49810
movq %rax, 0x80(%rsp)
jmp 0x428f5
movq 0x80(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x68(%rsp)
movl 0x1a4(%rsp), %esi
leaq 0xa00(%rsp), %rdi
callq 0x49810
movq %rax, 0x70(%rsp)
jmp 0x42920
movq 0x68(%rsp), %rsi
movq 0x78(%rsp), %rdi
movq 0x70(%rsp), %rax
movq (%rax), %rdx
callq 0x57590
jmp 0x42939
jmp 0x4293b
movl 0x1a4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1a4(%rsp)
jmp 0x42890
jmp 0x4296b
jmp 0x42955
movl 0x5d0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x5d0(%rsp)
jmp 0x426d6
jmp 0x4296d
movl 0x9e8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x9e8(%rsp)
jmp 0x42489
movq 0x160(%rsp), %rdi
movq 0x9f0(%rsp), %rsi
callq 0x2c920
movq %rax, 0x60(%rsp)
jmp 0x4299f
movq 0x60(%rsp), %rax
movq %rax, 0x198(%rsp)
cmpq $0x0, 0x198(%rsp)
je 0x42a7e
movl $0x0, 0x194(%rsp)
movl 0x194(%rsp), %eax
movl %eax, 0x58(%rsp)
leaq 0x1a40(%rsp), %rdi
callq 0x2b8b0
movl %eax, 0x5c(%rsp)
jmp 0x429e4
movl 0x58(%rsp), %eax
movl 0x5c(%rsp), %ecx
cmpl %ecx, %eax
jge 0x42a7c
movq 0x198(%rsp), %rdi
callq 0x2b510
movq %rax, 0x50(%rsp)
jmp 0x42a08
movl 0x194(%rsp), %esi
leaq 0x1a40(%rsp), %rdi
callq 0x49810
movq %rax, 0x48(%rsp)
jmp 0x42a23
movq 0x48(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x38(%rsp)
movl 0x194(%rsp), %esi
leaq 0xa00(%rsp), %rdi
callq 0x49810
movq %rax, 0x40(%rsp)
jmp 0x42a4b
movq 0x38(%rsp), %rsi
movq 0x50(%rsp), %rdi
movq 0x40(%rsp), %rax
movq (%rax), %rdx
callq 0x57590
jmp 0x42a64
jmp 0x42a66
movl 0x194(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x194(%rsp)
jmp 0x429c6
jmp 0x42a7e
movl $0x0, 0x1a1c(%rsp)
leaq 0xa00(%rsp), %rdi
callq 0x49830
movl 0x1a1c(%rsp), %eax
movl %eax, 0x34(%rsp)
testl %eax, %eax
je 0x42ab9
jmp 0x42aa7
movl 0x34(%rsp), %eax
subl $0x7, %eax
je 0x42270
jmp 0x42c90
jmp 0x42270
movq 0x2a58(%rsp), %rdi
callq 0x229d0
jmp 0x42acd
leaq 0x180(%rsp), %rdi
callq 0x48140
jmp 0x42adc
movl $0x0, 0x17c(%rsp)
movq 0x160(%rsp), %rdi
movl 0x17c(%rsp), %eax
movl %eax, 0x2c(%rsp)
callq 0x2bf50
movl %eax, 0x30(%rsp)
jmp 0x42b05
movl 0x2c(%rsp), %eax
movl 0x30(%rsp), %ecx
cmpl %ecx, %eax
jge 0x42b7b
movq 0x160(%rsp), %rdi
movl 0x17c(%rsp), %esi
callq 0x2bf70
movq %rax, 0x20(%rsp)
jmp 0x42b2c
movq 0x20(%rsp), %rsi
leaq 0x180(%rsp), %rdi
callq 0x48340
jmp 0x42b40
jmp 0x42b42
movl 0x17c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x17c(%rsp)
jmp 0x42ae7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1a38(%rsp)
movl %eax, 0x1a34(%rsp)
leaq 0x180(%rsp), %rdi
callq 0x48210
jmp 0x42c9f
movl $0x0, 0x178(%rsp)
movl 0x178(%rsp), %eax
movl %eax, 0x18(%rsp)
leaq 0x180(%rsp), %rdi
callq 0x2b8b0
movl %eax, 0x1c(%rsp)
jmp 0x42ba4
movl 0x18(%rsp), %eax
movl 0x1c(%rsp), %ecx
cmpl %ecx, %eax
jge 0x42c6d
movl 0x178(%rsp), %esi
leaq 0x180(%rsp), %rdi
callq 0x2bd10
movq %rax, 0x10(%rsp)
jmp 0x42bcf
movq 0x10(%rsp), %rax
movq %rax, 0x170(%rsp)
movq 0x170(%rsp), %rdi
leaq 0x14ca67(%rip), %rsi    # 0x18f652
callq 0x49840
movq %rax, 0x8(%rsp)
jmp 0x42bf7
movq 0x8(%rsp), %rax
movq %rax, 0x168(%rsp)
cmpq $0x0, 0x168(%rsp)
jne 0x42c11
jmp 0x42c57
movq 0x168(%rsp), %rdi
leaq 0x153487(%rip), %rsi    # 0x1960a7
callq 0x22ec0
cmpl $0x0, %eax
je 0x42c2c
jmp 0x42c57
movq 0x170(%rsp), %rax
movq %rax, (%rsp)
cmpq $0x0, %rax
je 0x42c55
movq (%rsp), %rdi
callq 0x55a60
movq (%rsp), %rdi
movl $0x1b0, %esi            # imm = 0x1B0
callq 0x22a00
jmp 0x42c57
movl 0x178(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x178(%rsp)
jmp 0x42b86
movl $0x1, 0x2a74(%rsp)
movl $0x1, 0x1a1c(%rsp)
leaq 0x180(%rsp), %rdi
callq 0x48210
leaq 0x1a40(%rsp), %rdi
callq 0x49830
jmp 0x42cae
leaq 0x1a40(%rsp), %rdi
callq 0x49830
jmp 0x42cbd
movl 0x2a74(%rsp), %eax
addq $0x2a78, %rsp           # imm = 0x2A78
retq
movq 0x1a38(%rsp), %rdi
callq 0x23290
nopw (%rax,%rax)