// File: graphitemaster[P]smbf/smbf.cpp
// Function: main
int main(int argc, char **argv) {
    --argc;
    ++argv;
    bool tangents = false;
    bool bitangents = false;
    const char *file = nullptr;

    for (int i = 0; i < argc; i++) {
        if (!strcmp(argv[i], "-t"))
            tangents = true;
        else if (!strcmp(argv[i], "-b"))
            bitangents = true;
        else
            file = argv[i];
    }

    if (!file) {
        fprintf(stderr, "expected OBJ file name\n");
        return 1;
    }

    int before = 0;
    int after = 0;
    obj o;
    if (!o.load(file, before, after)) {
        fprintf(stderr, "failed to load OBJ model `%s'\n", file);
        return 1;
    }

    int format = SMBF_FORMAT_P;
    if (o.m_normals.size())
        format = SMBF_FORMAT_PN;
    if (o.m_coordinates.size())
        format = SMBF_FORMAT_PNC;
    if (o.m_tangents.size() && tangents)
        format = SMBF_FORMAT_PNCT;
    if (o.m_bitangents.size() && bitangents)
        format = SMBF_FORMAT_PNCTB;


    const char *formats[] = {
        "P", "PN", "PNC", "PNCT", "PNCTB"
    };

    header h;
    h.magic[0] = 'S';
    h.magic[1] = 'M';
    h.magic[2] = 'B';
    h.magic[3] = 'F';
    h.version = SMBF_VERSION;
    h.format = format;
    h.count = o.m_positions.size();
    h.indices = o.m_indices.size();

    // Interleave the data
    union data {
        smbfP asP;
        smbfPN asPN;
        smbfPNC asPNC;
        smbfPNCT asPNCT;
        smbfPNCTB asPNCTB;
    };
    u::vector<data> inter;
    inter.resize(h.count);
    for (size_t i = 0; i < h.count; i++) {
        data &x = inter[i];
        smbfPNCTB &s = x.asPNCTB;
        s.px = o.m_positions[i].x;
        s.py = o.m_positions[i].y;
        s.pz = o.m_positions[i].z;
        if (o.m_normals.size()) {
            s.nx = o.m_normals[i].x;
            s.ny = o.m_normals[i].y;
            s.nz = o.m_normals[i].z;
        }
        if (o.m_coordinates.size()) {
            s.tu = o.m_coordinates[i].x;
            s.tv = o.m_coordinates[i].y;
        }
        s.tx = o.m_tangents[i].x;
        s.ty = o.m_tangents[i].y;
        s.tz = o.m_tangents[i].z;
        s.b = o.m_bitangents[i];
    }

    u::string name(file, strrchr(file, '.'));
    name += ".smbf";
    u::file write = u::fopen(name, "w");
    if (!write) {
        fprintf(stderr, "failed to open `%s' for writing\n", name.c_str());
        return 1;
    }

    fwrite(&h, sizeof(header), 1, write);
    for (auto &it : inter) {
        switch (format) {
        case SMBF_FORMAT_P:
            fwrite(&it.asP, sizeof(smbfP), 1, write);
            break;
        case SMBF_FORMAT_PN:
            fwrite(&it.asPN, sizeof(smbfPN), 1, write);
            break;
        case SMBF_FORMAT_PNC:
            fwrite(&it.asPNC, sizeof(smbfPNC), 1, write);
            break;
        case SMBF_FORMAT_PNCT:
            fwrite(&it.asPNCT, sizeof(smbfPNCT), 1, write);
            break;
        case SMBF_FORMAT_PNCTB:
            fwrite(&it.asPNCTB, sizeof(smbfPNCTB), 1, write);
            break;
        }
    }

    for (auto &it : o.m_indices) {
        uint32_t convert = it;
        fwrite(&convert, sizeof(uint32_t), 1, write);
    }

    printf("Wrote `%s':\n", name.c_str());
    printf(" Indices:\n");
    printf("  Count: %i\n", int(h.indices));
    printf("  Cache misses:\n");
    printf("   Before: %i\n", before);
    printf("   After:  %i\n", after);
    printf(" Vertices:\n");
    printf("  Count:  %i\n", int(h.count));
    printf("  Format: %s\n", formats[format]);
    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x260, %rsp            # imm = 0x260
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl -0x8(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x8(%rbp)
movq -0x10(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x10(%rbp)
movb $0x0, -0x11(%rbp)
movb $0x0, -0x12(%rbp)
movq $0x0, -0x20(%rbp)
movl $0x0, -0x24(%rbp)
movl -0x24(%rbp), %eax
cmpl -0x8(%rbp), %eax
jge 0x51e2
movq -0x10(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
leaq 0xaf64(%rip), %rsi      # 0x100f4
callq 0x22a0
cmpl $0x0, %eax
jne 0x51a0
movb $0x1, -0x11(%rbp)
jmp 0x51d5
movq -0x10(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
leaq 0xaf44(%rip), %rsi      # 0x100f7
callq 0x22a0
cmpl $0x0, %eax
jne 0x51c3
movb $0x1, -0x12(%rbp)
jmp 0x51d3
movq -0x10(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x20(%rbp)
jmp 0x51d5
jmp 0x51d7
movl -0x24(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x24(%rbp)
jmp 0x5175
cmpq $0x0, -0x20(%rbp)
jne 0x520d
movq 0x12de8(%rip), %rax     # 0x17fd8
movq (%rax), %rdi
leaq 0xaf00(%rip), %rsi      # 0x100fa
movb $0x0, %al
callq 0x22b0
movl $0x1, -0x4(%rbp)
jmp 0x5bf0
movl $0x0, -0x28(%rbp)
movl $0x0, -0x2c(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x8040
movq -0x20(%rbp), %rax
movq %rax, -0x1f8(%rbp)
leaq -0xe1(%rbp), %rdi
movq %rdi, -0x1f0(%rbp)
callq 0x2340
movq -0x1f8(%rbp), %rsi
movq -0x1f0(%rbp), %rdx
leaq -0xe0(%rbp), %rdi
callq 0x80a0
jmp 0x5261
leaq -0xc0(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
leaq -0x28(%rbp), %rdx
leaq -0x2c(%rbp), %rcx
callq 0x3ab0
movb %al, -0x1f9(%rbp)
jmp 0x5284
movb -0x1f9(%rbp), %al
xorb $-0x1, %al
movb %al, -0x1fa(%rbp)
leaq -0xe0(%rbp), %rdi
callq 0x2110
leaq -0xe1(%rbp), %rdi
callq 0x2200
movb -0x1fa(%rbp), %al
testb $0x1, %al
jne 0x52b6
jmp 0x532b
movq 0x12d1b(%rip), %rax     # 0x17fd8
movq (%rax), %rdi
movq -0x20(%rbp), %rdx
leaq 0xae47(%rip), %rsi      # 0x10112
movb $0x0, %al
callq 0x22b0
movl $0x1, -0x4(%rbp)
movl $0x1, -0xf8(%rbp)
jmp 0x5bd4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf0(%rbp)
movl %eax, -0xf4(%rbp)
jmp 0x531a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf0(%rbp)
movl %eax, -0xf4(%rbp)
leaq -0xe0(%rbp), %rdi
callq 0x2110
leaq -0xe1(%rbp), %rdi
callq 0x2200
jmp 0x5be2
movl $0x0, -0xfc(%rbp)
leaq -0xc0(%rbp), %rdi
addq $0x30, %rdi
callq 0x7dd0
cmpq $0x0, %rax
je 0x5355
movl $0x1, -0xfc(%rbp)
leaq -0xc0(%rbp), %rdi
addq $0x48, %rdi
callq 0x7dd0
cmpq $0x0, %rax
je 0x5375
movl $0x2, -0xfc(%rbp)
leaq -0xc0(%rbp), %rdi
addq $0x60, %rdi
callq 0x7dd0
cmpq $0x0, %rax
je 0x539b
testb $0x1, -0x11(%rbp)
je 0x539b
movl $0x3, -0xfc(%rbp)
leaq -0xc0(%rbp), %rdi
addq $0x78, %rdi
callq 0x8150
cmpq $0x0, %rax
je 0x53c1
testb $0x1, -0x12(%rbp)
je 0x53c1
movl $0x4, -0xfc(%rbp)
movq 0x129e8(%rip), %rax     # 0x17db0
movq %rax, -0x110(%rbp)
movaps 0x129ca(%rip), %xmm0    # 0x17da0
movaps %xmm0, -0x120(%rbp)
movaps 0x129ac(%rip), %xmm0    # 0x17d90
movaps %xmm0, -0x130(%rbp)
movb $0x53, -0x140(%rbp)
movb $0x4d, -0x13f(%rbp)
movb $0x42, -0x13e(%rbp)
movb $0x46, -0x13d(%rbp)
movw $0x100, -0x13a(%rbp)    # imm = 0x100
movb -0xfc(%rbp), %al
movb %al, -0x13c(%rbp)
leaq -0xa8(%rbp), %rdi
callq 0x7dd0
movl %eax, -0x138(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x6e30
movl %eax, -0x134(%rbp)
leaq -0x158(%rbp), %rdi
movq %rdi, -0x208(%rbp)
callq 0x5c10
movq -0x208(%rbp), %rdi
movl -0x138(%rbp), %eax
movl %eax, %esi
callq 0x5c30
jmp 0x5469
movq $0x0, -0x160(%rbp)
movq -0x160(%rbp), %rax
movl -0x138(%rbp), %ecx
cmpq %rcx, %rax
jae 0x56ec
movq -0x160(%rbp), %rsi
leaq -0x158(%rbp), %rdi
callq 0x5cc0
movq %rax, -0x168(%rbp)
movq -0x168(%rbp), %rax
movq %rax, -0x170(%rbp)
leaq -0xc0(%rbp), %rdi
addq $0x18, %rdi
movq -0x160(%rbp), %rsi
callq 0x7db0
movss (%rax), %xmm0
movq -0x170(%rbp), %rax
movss %xmm0, (%rax)
leaq -0xc0(%rbp), %rdi
addq $0x18, %rdi
movq -0x160(%rbp), %rsi
callq 0x7db0
movss 0x4(%rax), %xmm0
movq -0x170(%rbp), %rax
movss %xmm0, 0x4(%rax)
leaq -0xc0(%rbp), %rdi
addq $0x18, %rdi
movq -0x160(%rbp), %rsi
callq 0x7db0
movss 0x8(%rax), %xmm0
movq -0x170(%rbp), %rax
movss %xmm0, 0x8(%rax)
leaq -0xc0(%rbp), %rdi
addq $0x30, %rdi
callq 0x7dd0
cmpq $0x0, %rax
je 0x55d2
leaq -0xc0(%rbp), %rdi
addq $0x30, %rdi
movq -0x160(%rbp), %rsi
callq 0x7db0
movss (%rax), %xmm0
movq -0x170(%rbp), %rax
movss %xmm0, 0xc(%rax)
leaq -0xc0(%rbp), %rdi
addq $0x30, %rdi
movq -0x160(%rbp), %rsi
callq 0x7db0
movss 0x4(%rax), %xmm0
movq -0x170(%rbp), %rax
movss %xmm0, 0x10(%rax)
leaq -0xc0(%rbp), %rdi
addq $0x30, %rdi
movq -0x160(%rbp), %rsi
callq 0x7db0
movss 0x8(%rax), %xmm0
movq -0x170(%rbp), %rax
movss %xmm0, 0x14(%rax)
jmp 0x55d2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf0(%rbp)
movl %eax, -0xf4(%rbp)
jmp 0x5bc6
leaq -0xc0(%rbp), %rdi
addq $0x48, %rdi
callq 0x7dd0
cmpq $0x0, %rax
je 0x5637
leaq -0xc0(%rbp), %rdi
addq $0x48, %rdi
movq -0x160(%rbp), %rsi
callq 0x7db0
movss (%rax), %xmm0
movq -0x170(%rbp), %rax
movss %xmm0, 0x18(%rax)
leaq -0xc0(%rbp), %rdi
addq $0x48, %rdi
movq -0x160(%rbp), %rsi
callq 0x7db0
movss 0x4(%rax), %xmm0
movq -0x170(%rbp), %rax
movss %xmm0, 0x1c(%rax)
leaq -0xc0(%rbp), %rdi
addq $0x60, %rdi
movq -0x160(%rbp), %rsi
callq 0x7db0
movss (%rax), %xmm0
movq -0x170(%rbp), %rax
movss %xmm0, 0x20(%rax)
leaq -0xc0(%rbp), %rdi
addq $0x60, %rdi
movq -0x160(%rbp), %rsi
callq 0x7db0
movss 0x4(%rax), %xmm0
movq -0x170(%rbp), %rax
movss %xmm0, 0x24(%rax)
leaq -0xc0(%rbp), %rdi
addq $0x60, %rdi
movq -0x160(%rbp), %rsi
callq 0x7db0
movss 0x8(%rax), %xmm0
movq -0x170(%rbp), %rax
movss %xmm0, 0x28(%rax)
leaq -0xc0(%rbp), %rdi
addq $0x78, %rdi
movq -0x160(%rbp), %rsi
callq 0x8170
movss (%rax), %xmm0
movq -0x170(%rbp), %rax
movss %xmm0, 0x2c(%rax)
movq -0x160(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x160(%rbp)
jmp 0x5474
movq -0x20(%rbp), %rdi
movq %rdi, -0x220(%rbp)
movl $0x2e, %esi
callq 0x2230
movq %rax, -0x218(%rbp)
leaq -0x191(%rbp), %rdi
movq %rdi, -0x210(%rbp)
callq 0x2340
movq -0x220(%rbp), %rsi
movq -0x218(%rbp), %rdx
movq -0x210(%rbp), %rcx
leaq -0x190(%rbp), %rdi
callq 0x8190
jmp 0x573e
leaq -0x191(%rbp), %rdi
callq 0x2200
leaq 0xa9f4(%rip), %rsi      # 0x10145
leaq -0x190(%rbp), %rdi
callq 0x21b0
jmp 0x575f
leaq 0xa9e5(%rip), %rdx      # 0x1014b
leaq -0x1a0(%rbp), %rdi
leaq -0x190(%rbp), %rsi
callq 0x2560
jmp 0x577b
leaq -0x1a0(%rbp), %rdi
callq 0x2520
cmpq $0x0, %rax
jne 0x5816
movq 0x12840(%rip), %rax     # 0x17fd8
movq (%rax), %rax
movq %rax, -0x228(%rbp)
leaq -0x190(%rbp), %rdi
callq 0x20a0
movq -0x228(%rbp), %rdi
movq %rax, %rdx
leaq 0xa98e(%rip), %rsi      # 0x1014d
movb $0x0, %al
callq 0x22b0
movl $0x1, -0x4(%rbp)
movl $0x1, -0xf8(%rbp)
jmp 0x5b94
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf0(%rbp)
movl %eax, -0xf4(%rbp)
leaq -0x191(%rbp), %rdi
callq 0x2200
jmp 0x5bc6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf0(%rbp)
movl %eax, -0xf4(%rbp)
jmp 0x5bba
leaq -0x1a0(%rbp), %rdi
callq 0x2520
movq %rax, %rcx
leaq -0x140(%rbp), %rdi
movl $0x10, %esi
movl $0x1, %edx
callq 0x2370
jmp 0x583d
leaq -0x158(%rbp), %rax
movq %rax, -0x1a8(%rbp)
movq -0x1a8(%rbp), %rdi
callq 0x5ce0
movq %rax, -0x1b0(%rbp)
movq -0x1a8(%rbp), %rdi
callq 0x5d10
movq %rax, -0x1b8(%rbp)
leaq -0x1b0(%rbp), %rdi
leaq -0x1b8(%rbp), %rsi
callq 0x5d40
testb $0x1, %al
jne 0x588d
jmp 0x5a1d
leaq -0x1b0(%rbp), %rdi
callq 0x5d80
movq %rax, -0x1c0(%rbp)
movl -0xfc(%rbp), %eax
movq %rax, -0x230(%rbp)
subq $0x4, %rax
ja 0x5a0a
movq -0x230(%rbp), %rax
leaq 0xa76b(%rip), %rcx      # 0x10030
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf0(%rbp)
movl %eax, -0xf4(%rbp)
leaq -0x1a0(%rbp), %rdi
callq 0x24e0
jmp 0x5bba
movq -0x1c0(%rbp), %rax
movq %rax, -0x238(%rbp)
leaq -0x1a0(%rbp), %rdi
callq 0x2520
movq -0x238(%rbp), %rdi
movq %rax, %rcx
movl $0xc, %esi
movl $0x1, %edx
callq 0x2370
jmp 0x5926
jmp 0x5a0a
movq -0x1c0(%rbp), %rax
movq %rax, -0x240(%rbp)
leaq -0x1a0(%rbp), %rdi
callq 0x2520
movq -0x240(%rbp), %rdi
movq %rax, %rcx
movl $0x18, %esi
movl $0x1, %edx
callq 0x2370
jmp 0x5960
jmp 0x5a0a
movq -0x1c0(%rbp), %rax
movq %rax, -0x248(%rbp)
leaq -0x1a0(%rbp), %rdi
callq 0x2520
movq -0x248(%rbp), %rdi
movq %rax, %rcx
movl $0x20, %esi
movl $0x1, %edx
callq 0x2370
jmp 0x599a
jmp 0x5a0a
movq -0x1c0(%rbp), %rax
movq %rax, -0x250(%rbp)
leaq -0x1a0(%rbp), %rdi
callq 0x2520
movq -0x250(%rbp), %rdi
movq %rax, %rcx
movl $0x2c, %esi
movl $0x1, %edx
callq 0x2370
jmp 0x59d1
jmp 0x5a0a
movq -0x1c0(%rbp), %rax
movq %rax, -0x258(%rbp)
leaq -0x1a0(%rbp), %rdi
callq 0x2520
movq -0x258(%rbp), %rdi
movq %rax, %rcx
movl $0x30, %esi
movl $0x1, %edx
callq 0x2370
jmp 0x5a08
jmp 0x5a0a
jmp 0x5a0c
leaq -0x1b0(%rbp), %rdi
callq 0x5da0
jmp 0x5871
leaq -0xc0(%rbp), %rax
movq %rax, -0x1c8(%rbp)
movq -0x1c8(%rbp), %rdi
callq 0x6f00
movq %rax, -0x1d0(%rbp)
movq -0x1c8(%rbp), %rdi
callq 0x7800
movq %rax, -0x1d8(%rbp)
leaq -0x1d0(%rbp), %rdi
leaq -0x1d8(%rbp), %rsi
callq 0x7830
testb $0x1, %al
jne 0x5a6a
jmp 0x5ac3
leaq -0x1d0(%rbp), %rdi
callq 0x7870
movq %rax, -0x1e0(%rbp)
movq -0x1e0(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x1e4(%rbp)
leaq -0x1a0(%rbp), %rdi
callq 0x2520
movq %rax, %rcx
leaq -0x1e4(%rbp), %rdi
movl $0x4, %esi
movl $0x1, %edx
callq 0x2370
jmp 0x5ab3
jmp 0x5ab5
leaq -0x1d0(%rbp), %rdi
callq 0x7890
jmp 0x5a51
leaq -0x190(%rbp), %rdi
callq 0x20a0
movq %rax, %rsi
leaq 0xa695(%rip), %rdi      # 0x1016e
xorl %eax, %eax
callq 0x2030
jmp 0x5ae2
leaq 0xa692(%rip), %rdi      # 0x1017b
xorl %eax, %eax
callq 0x2030
jmp 0x5af2
movl -0x134(%rbp), %esi
leaq 0xa687(%rip), %rdi      # 0x10186
xorl %eax, %eax
callq 0x2030
jmp 0x5b08
leaq 0xa684(%rip), %rdi      # 0x10193
xorl %eax, %eax
callq 0x2030
jmp 0x5b18
movl -0x28(%rbp), %esi
leaq 0xa682(%rip), %rdi      # 0x101a4
xorl %eax, %eax
callq 0x2030
jmp 0x5b2b
movl -0x2c(%rbp), %esi
leaq 0xa67e(%rip), %rdi      # 0x101b3
xorl %eax, %eax
callq 0x2030
jmp 0x5b3e
leaq 0xa67d(%rip), %rdi      # 0x101c2
xorl %eax, %eax
callq 0x2030
jmp 0x5b4e
movl -0x138(%rbp), %esi
leaq 0xa673(%rip), %rdi      # 0x101ce
xorl %eax, %eax
callq 0x2030
jmp 0x5b64
movslq -0xfc(%rbp), %rax
movq -0x130(%rbp,%rax,8), %rsi
leaq 0xa662(%rip), %rdi      # 0x101dc
xorl %eax, %eax
callq 0x2030
jmp 0x5b83
movl $0x0, -0x4(%rbp)
movl $0x1, -0xf8(%rbp)
leaq -0x1a0(%rbp), %rdi
callq 0x24e0
leaq -0x190(%rbp), %rdi
callq 0x2110
leaq -0x158(%rbp), %rdi
callq 0x5dc0
jmp 0x5bd4
leaq -0x190(%rbp), %rdi
callq 0x2110
leaq -0x158(%rbp), %rdi
callq 0x5dc0
jmp 0x5be2
leaq -0xc0(%rbp), %rdi
callq 0x8200
jmp 0x5bf0
leaq -0xc0(%rbp), %rdi
callq 0x8200
jmp 0x5bfc
movl -0x4(%rbp), %eax
addq $0x260, %rsp            # imm = 0x260
popq %rbp
retq
movq -0xf0(%rbp), %rdi
callq 0x2330
nopl (%rax,%rax)