user: Converte this assembly snippet into its equivalent C code:

```asm
<pack_nametable>:
  endbr64
  push   %r15
  push   %r14
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  sub    $0x48,%rsp
  mov    %rdi,0x8(%rsp)
  mov    %esi,%r14d
  mov    %esi,0x38(%rsp)
  mov    %edx,%ebp
  mov    %edx,0x10(%rsp)
  mov    %ecx,%ebx
  mov    %r8d,0x3c(%rsp)
  mov    %r9,%r15
  mov    $0x0,%eax
  call   <assert@plt>
  mov    %r15,%rdi
  mov    $0x0,%eax
  call   <assert@plt>
  mov    0x80(%rsp),%rdi
  mov    $0x0,%eax
  call   <assert@plt>
  movq   $0x0,(%r15)
  test   %r14d,%r14d
  jle    L430
  mov    %ebx,0x30(%rsp)
  mov    %ebp,0x34(%rsp)
  mov    $0x0,%r13d
  movl   $0x0,0x18(%rsp)
  mov    $0x0,%r14d
  jmp    L414
L348:
  cmp    $0x3,%ebx
  jne    L456
  lea    0x3(%rbp),%edx
  cmp    0x10(%rsp),%edx
  jge    L389
  mov    0x8(%rsp),%rcx
  cmp    %r12b,0x1(%rcx,%rax,1)
  je     L269
L389:
  lea    0x1(%r14),%eax
  mov    %eax,0x28(%rsp)
  cmp    %eax,0x18(%rsp)
  jle    L235
L398:
  movslq %r14d,%r14
  mov    (%r15),%rax
  mov    %r12b,(%rax,%r14,1)
  add    $0x1,%r13d
  add    $0x1,%ebp
  addl   $0x1,0x14(%rsp)
  mov    0x14(%rsp),%eax
  mov    0x28(%rsp),%r14d
  movl   $0x0,0x1c(%rsp)
  cmp    $0x3f,%eax
  je     L396
L87:
  movslq %r13d,%rax
L456:
  cmp    0x10(%rsp),%ebp
  jge    L330
  mov    0x8(%rsp),%rsi
  movzbl (%rsi,%rax,1),%r12d
  cmp    $0x2,%ebx
  je     L22
  jg     L348
  test   %ebx,%ebx
  je     L183
  cmp    $0x1,%ebx
  jne    L456
L425:
  test   %r12b,%r12b
  jne    L285
  add    $0x1,%r13d
  add    $0x1,%ebp
  addl   $0x1,0x20(%rsp)
  movl   $0x0,0x1c(%rsp)
  jmp    L87
L183:
  lea    0x3(%rbp),%edx
  mov    %ebx,0x1c(%rsp)
  cmp    0x10(%rsp),%edx
  jge    L425
  mov    0x8(%rsp),%rcx
  cmp    %r12b,0x1(%rcx,%rax,1)
  jne    L425
  cmp    %r12b,0x2(%rcx,%rax,1)
  jne    L425
  cmp    %r12b,0x3(%rcx,%rax,1)
  sete   %al
  movzbl %al,%eax
  mov    %eax,0x1c(%rsp)
  jmp    L425
L285:
  lea    0x2(%r14),%ebx
  cmp    0x18(%rsp),%ebx
  jge    L140
L433:
  movslq %r14d,%rax
  mov    (%r15),%rdx
  mov    0x20(%rsp),%ecx
  movzbl %ch,%ecx
  mov    %cl,(%rdx,%rax,1)
  lea    0x1(%r14),%eax
  cltq
  mov    (%r15),%rdx
  movzbl 0x20(%rsp),%ecx
  mov    %cl,(%rdx,%rax,1)
  cmpl   $0x0,0x1c(%rsp)
  je     L139
  add    $0x4,%r13d
  add    $0x4,%ebp
  mov    %r12b,0x27(%rsp)
  mov    %ebx,%r14d
  mov    $0x2,%ebx
  movl   $0x4,0x14(%rsp)
  jmp    L87
L140:
  addl   $0x40,0x18(%rsp)
  mov    0x18(%rsp),%eax
  movslq %eax,%rsi
  mov    (%r15),%rdi
  call   <realloc@plt>
  mov    %rax,(%r15)
  jmp    L433
L139:
  lea    0x4(%r14),%eax
  mov    %eax,0x14(%rsp)
  cmp    0x18(%rsp),%eax
  jge    L47
L141:
  movslq %ebx,%rax
  mov    (%r15),%rdx
  movb   $0x0,(%rdx,%rax,1)
  add    $0x3,%r14d
  movslq %r14d,%r14
  mov    (%r15),%rax
  mov    %r12b,(%rax,%r14,1)
  add    $0x1,%r13d
  add    $0x1,%ebp
  mov    %ebx,0x2c(%rsp)
  mov    0x14(%rsp),%r14d
  mov    $0x3,%ebx
  movl   $0x1,0x14(%rsp)
  jmp    L87
L47:
  addl   $0x40,0x18(%rsp)
  mov    0x18(%rsp),%eax
  movslq %eax,%rsi
  mov    (%r15),%rdi
  call   <realloc@plt>
  mov    %rax,(%r15)
  jmp    L141
L22:
  cmp    %r12b,0x27(%rsp)
  je     L38
L185:
  lea    0x2(%r14),%ebx
  cmp    0x18(%rsp),%ebx
  jge    L125
L143:
  movslq %r14d,%rax
  mov    (%r15),%rdx
  mov    0x14(%rsp),%edi
  mov    %edi,%ecx
  or     $0x40,%ecx
  mov    %cl,(%rdx,%rax,1)
  add    $0x1,%r14d
  movslq %r14d,%r14
  mov    (%r15),%rax
  movzbl 0x27(%rsp),%esi
  mov    %sil,(%rax,%r14,1)
  add    %edi,0x20(%rsp)
  mov    %ebx,%r14d
  mov    $0x0,%ebx
  jmp    L87
L38:
  addl   $0x1,0x14(%rsp)
  mov    0x14(%rsp),%eax
  add    $0x1,%r13d
  add    $0x1,%ebp
  cmp    $0x3f,%eax
  je     L185
  mov    %r12b,0x27(%rsp)
  jmp    L87
L125:
  addl   $0x40,0x18(%rsp)
  mov    0x18(%rsp),%eax
  movslq %eax,%rsi
  mov    (%r15),%rdi
  call   <realloc@plt>
  mov    %rax,(%r15)
  jmp    L143
L269:
  cmp    %r12b,0x2(%rcx,%rax,1)
  jne    L389
  cmp    %r12b,0x3(%rcx,%rax,1)
  jne    L389
  movslq 0x2c(%rsp),%rax
  mov    (%r15),%rdx
  mov    0x14(%rsp),%edi
  mov    %dil,(%rdx,%rax,1)
  add    %edi,0x20(%rsp)
  movl   $0x1,0x1c(%rsp)
  mov    $0x1,%ebx
  jmp    L87
L235:
  addl   $0x40,0x18(%rsp)
  mov    0x18(%rsp),%eax
  movslq %eax,%rsi
  mov    (%r15),%rdi
  call   <realloc@plt>
  mov    %rax,(%r15)
  jmp    L398
L396:
  movslq 0x2c(%rsp),%rax
  mov    (%r15),%rdx
  movb   $0x3f,(%rdx,%rax,1)
  addl   $0x3f,0x20(%rsp)
  mov    $0x1,%ebx
  jmp    L87
L330:
  cmp    $0x2,%ebx
  je     L209
  cmp    $0x3,%ebx
  je     L241
L334:
  mov    0x34(%rsp),%edi
  mov    %edi,%eax
  add    0x10(%rsp),%eax
  addl   $0x20,0x30(%rsp)
  cmp    %edi,0x38(%rsp)
  jle    L281
  mov    %eax,0x34(%rsp)
L414:
  mov    0x30(%rsp),%eax
  mov    %eax,0x20(%rsp)
  movl   $0x0,0x1c(%rsp)
  mov    $0x0,%ebx
  mov    $0x0,%ebp
  jmp    L87
L209:
  lea    0x2(%r14),%ebx
  cmp    %ebx,0x18(%rsp)
  jle    L95
L90:
  movslq %r14d,%rax
  mov    (%r15),%rdx
  movzbl 0x14(%rsp),%ecx
  or     $0x40,%ecx
  mov    %cl,(%rdx,%rax,1)
  lea    0x1(%r14),%eax
  cltq
  mov    (%r15),%rdx
  movzbl 0x27(%rsp),%edi
  mov    %dil,(%rdx,%rax,1)
  mov    %ebx,%r14d
  jmp    L334
L95:
  addl   $0x40,0x18(%rsp)
  mov    0x18(%rsp),%eax
  movslq %eax,%rsi
  mov    (%r15),%rdi
  call   <realloc@plt>
  mov    %rax,(%r15)
  jmp    L90
L241:
  movslq 0x2c(%rsp),%rax
  mov    (%r15),%rdx
  movzbl 0x14(%rsp),%esi
  mov    %sil,(%rdx,%rax,1)
  jmp    L334
L281:
  cmpl   $0x0,0x3c(%rsp)
  je     L300
  lea    0x1(%r14),%ebx
  cmp    0x18(%rsp),%ebx
  jge    L260
L392:
  movslq %r14d,%rax
  mov    (%r15),%rdx
  movb   $0x0,(%rdx,%rax,1)
  mov    %ebx,%r14d
L300:
  mov    0x80(%rsp),%rax
  mov    %r14d,(%rax)
  add    $0x48,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
L430:
  mov    0x3c(%rsp),%r14d
  test   %r14d,%r14d
  je     L300
  movl   $0x0,0x18(%rsp)
  mov    $0x0,%r14d
  mov    $0x1,%ebx
L260:
  mov    0x18(%rsp),%esi
  add    $0x1,%esi
  movslq %esi,%rsi
  mov    (%r15),%rdi
  call   <realloc@plt>
  mov    %rax,(%r15)
  jmp    L392
```

assistant: ```c
void pack_nametable(const unsigned char *nametable, int nametable_sz, int width, int vram_address, int zero_terminate, unsigned char **out, int *out_sz) {
  int out_pos = 0;
  int buf_sz = 0;
  int y = 0;
  int in_pos = 0;
  assert(nametable);
  assert(out);
  assert(out_sz);
  *out = 0;
  while (y * width < nametable_sz) {
    unsigned char rlech;
    int count;
    int count_pos;
    int x = 0;
    int state = 0;
    int start_rle = 0;
    int addr = vram_address + (y * 32);
    while (x < width) {
      const unsigned char ch = nametable[in_pos];
      switch (state) {
      case 0:
        start_rle = (x + 4 <= width) && (nametable[in_pos + 1] == ch) && (nametable[in_pos + 2] == ch) && (nametable[in_pos + 3] == ch);
      case 1:
        if (ch == 0) {
          start_rle = 0;
          ++in_pos;
          ++x;
          ++addr;
          break;
        }
        if (out_pos + 2 >= buf_sz) {
          buf_sz += 64;
          *out = (unsigned char *)realloc(*out, buf_sz);
        }
        (*out)[out_pos++] = (unsigned char)(addr >> 8);
        (*out)[out_pos++] = (unsigned char)(addr & 255);
        if (start_rle) {
          count = 4;
          rlech = ch;
          in_pos += 4;
          x += 4;
          state = 2;
        } else {
          count_pos = out_pos;
          if (out_pos + 2 >= buf_sz) {
            buf_sz += 64;
            *out = (unsigned char *)realloc(*out, buf_sz);
          }
          (*out)[out_pos++] = 0;
          count = 1;
          (*out)[out_pos++] = ch;
          ++in_pos;
          ++x;
          state = 3;
        }
        break;
      case 2:
        if (ch == rlech) {
          ++count;
          ++in_pos;
          ++x;
        }
        if ((ch != rlech) || (count == 0x3F)) {
          if (out_pos + 2 >= buf_sz) {
            buf_sz += 64;
            *out = (unsigned char *)realloc(*out, buf_sz);
          }
          (*out)[out_pos++] = (unsigned char)(0x40 | count);
          (*out)[out_pos++] = rlech;
          addr += count;
          state = 0;
        }
        break;
      case 3:
        start_rle = ((x + 4 <= width) && (nametable[in_pos + 1] == ch) && (nametable[in_pos + 2] == ch) && (nametable[in_pos + 3] == ch));
        if (start_rle) {
          (*out)[count_pos] = count;
          addr += count;
          state = 1;
        } else {
          if (out_pos + 1 >= buf_sz) {
            buf_sz += 64;
            *out = (unsigned char *)realloc(*out, buf_sz);
          }
          (*out)[out_pos++] = ch;
          ++in_pos;
          ++x;
          ++count;
          if (count == 0x3F) {
            (*out)[count_pos] = count;
            addr += count;
            state = 1;
          }
        }
        break;
      }
    }
    switch (state) {
    case 0:
    case 1:
      break;
    case 2:
      if (out_pos + 2 >= buf_sz) {
        buf_sz += 64;
        *out = (unsigned char *)realloc(*out, buf_sz);
      }
      (*out)[out_pos++] = (unsigned char)(0x40 | count);
      (*out)[out_pos++] = rlech;
      break;
    case 3:
      (*out)[count_pos] = count;
      break;
    }
    ++y;
  }
  if (zero_terminate) {
    if (out_pos + 1 >= buf_sz) {
      buf_sz += 1;
      *out = (unsigned char *)realloc(*out, buf_sz);
    }
    (*out)[out_pos++] = 0;
  }
  *out_sz = out_pos;
}
```