// File: /workspace/github_c_makefile_star2_O2/FredTheDino[P]Fog/src/engine/unix_assets.cpp
// Function: dump_asset_file(AssetFile*, char const*)
void dump_asset_file(AssetFile *file, const char *out_path) {
    FILE *output_file = fopen(out_path, "wb");

    write_to_file(output_file, &file->header);
    u64 header_location = ftell(output_file);
    write_to_file(output_file, &file->asset_headers[0],
                  file->header.number_of_assets);

#ifdef GEN_SOURCE_FILE
#define WRITE_TO_SORUCE(...) fprintf(source_file, __VA_ARGS__)
    FILE *source_file = fopen("src/fog_assets.cpp", "w");
#else
#define WRITE_TO_SORUCE(...)
#endif
    WRITE_TO_SORUCE("// Don't edit this file, this file contains the asset ids\n"
                         "// for all assets in the game, and is autogenerated.\n"
                         "// Editing this file will result in a bad day.\n");
    std::vector<std::string> entiries;
    u64 string_begin = ftell(output_file);
    u64 string_cur = string_begin;
    // Write assets
    WRITE_TO_SORUCE("namespace Res {\n");
    for (u64 i = 0; i < file->asset_headers.size(); i++) {
        auto *header = &file->asset_headers[i];
        const char *asset_name = asset_name_from_file(header->file_path, header->type);
        printf("\tFound asset: %s -> %s\n", header->file_path,
               asset_name);
        WRITE_TO_SORUCE("constexpr Asset::AssetID %s = %llu;\n", asset_name, i);
        header->hash = Asset::asset_hash(asset_name);
        entiries.push_back(asset_name);
        free((void *) asset_name);

        write_to_file(output_file, header->file_path, header->file_path_length);
        header->file_path = (char *) (string_cur - string_begin);
        string_cur = ftell(output_file);
    }
    WRITE_TO_SORUCE("constexpr u64 NUM_ASSETS = %u;\n", (u32) entiries.size());

    WRITE_TO_SORUCE("\n// A hash table for absolute references outside\n// the code, used between builds of the engine, don't use these in your\n// game if you can avoid it.\n");
    // Write hash table
    std::unordered_set<u64> collisions;
    WRITE_TO_SORUCE("constexpr u64 HASH_LUT[] = {\n");
    for (u64 i = 0; i < entiries.size(); i++) {
        const char *c = entiries[i].c_str();
        u64 hash = Asset::asset_hash(c);
        ASSERT(collisions.count(hash) == 0, "Collision in asset system, update the hash function. (asset_hash)");
        WRITE_TO_SORUCE("    [%s] = %llu,\n", c, hash);
    }
    WRITE_TO_SORUCE("};");
    WRITE_TO_SORUCE("} // Namespace Res\n");
#ifdef GEN_SOURCE_FILE
    fclose(source_file);
#endif
    assert(string_cur - string_begin == file->header.size_of_strings);

    // Serialization of assets
    u64 data_begin = ftell(output_file);
    for (u64 i = 0; i < file->assets.size(); i++) {
        Asset::Data asset = file->assets[i];
        Asset::Header *header = &file->asset_headers[i];
        header->offset = ftell(output_file);
        switch (file->asset_headers[i].type) {
            case (Asset::Type::TEXTURE): {
                write_to_file(output_file, &asset);
                u64 size = asset.image.width * asset.image.height *
                           asset.image.components;
                write_to_file(output_file, asset.image.data, size);
            } break;
            case (Asset::Type::SHADER): {
                write_to_file(output_file, asset.shader_source, header->asset_size);
            } break;
            case (Asset::Type::FONT): {
                write_to_file(output_file, &asset);
                u64 num_glyphs = asset.font.num_glyphs;
                write_to_file(output_file, asset.font.glyphs, num_glyphs);
                u64 num_kernings = asset.font.num_kernings;
                write_to_file(output_file, asset.font.kernings, num_kernings);
            } break;
            case (Asset::Type::SOUND): {
                write_to_file(output_file, &asset);
                write_to_file(output_file, asset.sound.data, asset.sound.size);
            } break;
            case (Asset::Type::SPRITE): {
                write_to_file(output_file, &asset);
                write_to_file(output_file, asset.sprite.points, asset.sprite.num_points);
            } break;
            default:
                printf("UNIMPLEMENTED ASSET TYPE\n");
                continue;
                break;
        };
        header->asset_size = ftell(output_file) - header->offset;
    }
    u64 data_end = ftell(output_file);
    assert(data_end - data_begin == file->header.size_of_data);

    fseek(output_file, header_location, SEEK_SET);
    write_to_file(output_file, &file->asset_headers[0],
                  file->header.number_of_assets);

    fclose(output_file);
    printf("\tLoaded %lu assets\n", file->assets.size());
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xb8, %rsp
movq %rsi, %rax
movq %rdi, %rbx
leaq 0xcab7(%rip), %rsi      # 0x13b4e
movq %rax, %rdi
callq 0x2250
movq %rax, %r15
pushq $0x1
popq %rdx
movq %rax, %rdi
movq %rbx, %rsi
callq 0x10c8c
movq %r15, %rdi
callq 0x2030
movq %rax, -0xa8(%rbp)
movq (%rbx), %rdx
movq 0x20(%rbx), %rsi
movq %r15, %rdi
callq 0x10cd6
xorps %xmm0, %xmm0
leaq -0xa0(%rbp), %rax
movaps %xmm0, (%rax)
andq $0x0, 0x10(%rax)
movq %r15, %rdi
callq 0x2030
leaq -0xe0(%rbp), %r12
xorl %r14d, %r14d
xorl %esi, %esi
movq %rax, -0x80(%rbp)
movq %rax, -0x38(%rbp)
movq %r15, -0x30(%rbp)
movq %rbx, -0x78(%rbp)
movq %rbx, %rax
movq 0x20(%rbx), %rbx
movq 0x28(%rax), %rax
subq %rbx, %rax
cqto
pushq $0x38
popq %rcx
idivq %rcx
cmpq %rax, %rsi
jae 0x71d2
movq %rsi, -0x40(%rbp)
movq 0x8(%rbx,%r14), %rdi
movl (%rbx,%r14), %esi
callq 0x6fcb
movq %rax, %r15
movq 0x8(%rbx,%r14), %rsi
leaq 0xca0d(%rip), %rdi      # 0x13b51
movq %rax, %rdx
xorl %eax, %eax
callq 0x2050
movq %r15, %rdi
callq 0x42e3
movq %rax, 0x28(%rbx,%r14)
movq %r12, %rdi
movq %r15, %rsi
leaq -0x70(%rbp), %rdx
callq 0x10d1e
leaq -0xa0(%rbp), %rdi
movq %r12, %rsi
callq 0x11fb2
movq %r12, %r13
movq %r12, %rdi
callq 0x2100
movq %r15, %rdi
callq 0x2260
movq 0x8(%rbx,%r14), %rsi
movq 0x10(%rbx,%r14), %rdx
movq -0x30(%rbp), %r15
movq %r15, %rdi
callq 0x10d59
movq -0x38(%rbp), %rax
subq -0x80(%rbp), %rax
movq %rax, 0x8(%rbx,%r14)
movq %r15, %rdi
callq 0x2030
movq %rax, -0x38(%rbp)
movq -0x40(%rbp), %rsi
incq %rsi
addq $0x38, %r14
movq -0x78(%rbp), %rbx
movq %r13, %r12
jmp 0x7104
leaq -0xb0(%rbp), %rax
movq %rax, -0x30(%rax)
movq $0x1, -0x28(%rax)
xorps %xmm0, %xmm0
movups %xmm0, -0x20(%rax)
movl $0x3f800000, -0x10(%rax) # imm = 0x3F800000
movups %xmm0, -0x8(%rax)
xorl %ebx, %ebx
leaq -0xe0(%rbp), %r12
leaq 0xc68d(%rip), %r13      # 0x13894
leaq 0xc95b(%rip), %r15      # 0x13b69
xorl %r14d, %r14d
movq -0xa0(%rbp), %rax
movq -0x98(%rbp), %rcx
subq %rax, %rcx
sarq $0x5, %rcx
cmpq %rcx, %r14
jae 0x7265
movq (%rax,%rbx), %rdi
callq 0x42e3
movq %rax, -0x70(%rbp)
movq %r12, %rdi
leaq -0x70(%rbp), %rsi
callq 0x121a2
xorl %ecx, %ecx
testq %rax, %rax
sete %cl
movq %r13, %rdi
movl $0x1e6, %esi            # imm = 0x1E6
movq %r15, %rdx
callq 0x2736
incq %r14
addq $0x20, %rbx
jmp 0x7211
movq -0x38(%rbp), %rax
subq -0x80(%rbp), %rax
movq -0x78(%rbp), %rbx
cmpq 0x10(%rbx), %rax
jne 0x7487
movq -0x30(%rbp), %rdi
callq 0x2030
movq %rax, -0x40(%rbp)
xorl %r15d, %r15d
xorl %r13d, %r13d
xorl %edi, %edi
movq 0x38(%rbx), %rcx
movq 0x40(%rbx), %rax
subq %rcx, %rax
cqto
pushq $0x30
popq %rsi
idivq %rsi
cmpq %rax, %rdi
jae 0x73fa
movq %rdi, -0x38(%rbp)
movups (%rcx,%r15), %xmm0
movups 0x10(%rcx,%r15), %xmm1
movups 0x20(%rcx,%r15), %xmm2
movaps %xmm2, -0x50(%rbp)
movaps %xmm1, -0x60(%rbp)
movaps %xmm0, -0x70(%rbp)
movq 0x20(%rbx), %r14
movq -0x30(%rbp), %rdi
callq 0x2030
movq %rax, 0x20(%r14,%r13)
movq 0x20(%rbx), %rax
movl (%rax,%r13), %eax
decl %eax
cmpl $0x4, %eax
ja 0x73ec
leaq 0xbebb(%rip), %rcx      # 0x131b4
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x30(%rbp), %r12
movq %r12, %rdi
leaq -0x70(%rbp), %rsi
pushq $0x1
popq %rdx
callq 0x10d9f
movl -0x64(%rbp), %eax
imull -0x68(%rbp), %eax
movzbl -0x60(%rbp), %edx
imull %eax, %edx
movq -0x70(%rbp), %rsi
movq %r12, %rdi
callq 0x10de6
jmp 0x73c6
movq -0x70(%rbp), %rsi
movl 0x30(%r14,%r13), %edx
movq -0x30(%rbp), %r12
movq %r12, %rdi
callq 0x10d59
jmp 0x73c6
movq -0x30(%rbp), %r12
movq %r12, %rdi
leaq -0x70(%rbp), %rsi
pushq $0x1
popq %rdx
callq 0x10d9f
movq -0x60(%rbp), %rsi
movl -0x68(%rbp), %edx
movq %r12, %rdi
callq 0x10ec0
jmp 0x73c6
movq -0x30(%rbp), %r12
movq %r12, %rdi
leaq -0x70(%rbp), %rsi
pushq $0x1
popq %rdx
callq 0x10d9f
movq -0x70(%rbp), %rsi
movl -0x60(%rbp), %edx
movq %r12, %rdi
callq 0x10de6
jmp 0x73c6
movq -0x30(%rbp), %r12
movq %r12, %rdi
leaq -0x70(%rbp), %rsi
pushq $0x1
popq %rdx
callq 0x10d9f
movq -0x60(%rbp), %rdx
movq -0x50(%rbp), %rsi
movq %r12, %rdi
callq 0x10e2c
movq -0x58(%rbp), %rdx
movq -0x48(%rbp), %rsi
movq %r12, %rdi
callq 0x10e76
movq %r12, %rdi
callq 0x2030
subl 0x20(%r14,%r13), %eax
movl %eax, 0x30(%r14,%r13)
movq -0x38(%rbp), %rdi
incq %rdi
addq $0x38, %r13
addq $0x30, %r15
jmp 0x7290
leaq 0xd43a(%rip), %rdi      # 0x1482d
callq 0x2350
jmp 0x73d8
movq -0x30(%rbp), %r14
movq %r14, %rdi
callq 0x2030
subq -0x40(%rbp), %rax
cmpq 0x18(%rbx), %rax
jne 0x74a6
movq %r14, %rdi
movq -0xa8(%rbp), %rsi
xorl %edx, %edx
callq 0x2240
movq (%rbx), %rdx
movq 0x20(%rbx), %rsi
movq %r14, %rdi
callq 0x10cd6
movq %r14, %rdi
callq 0x21f0
movq 0x40(%rbx), %rax
subq 0x38(%rbx), %rax
cqto
pushq $0x30
popq %rcx
idivq %rcx
leaq 0xc812(%rip), %rdi      # 0x13c65
movq %rax, %rsi
xorl %eax, %eax
callq 0x2050
leaq -0xe0(%rbp), %rdi
callq 0x11046
leaq -0xa0(%rbp), %rdi
callq 0x10f0a
addq $0xb8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xc73a(%rip), %rdi      # 0x13bc8
leaq 0xc3ff(%rip), %rsi      # 0x13894
leaq 0xc766(%rip), %rcx      # 0x13c02
movl $0x1ee, %edx            # imm = 0x1EE
callq 0x2140
leaq 0xc785(%rip), %rdi      # 0x13c32
leaq 0xc3e0(%rip), %rsi      # 0x13894
leaq 0xc747(%rip), %rcx      # 0x13c02
movl $0x217, %edx            # imm = 0x217
callq 0x2140
jmp 0x74e7
jmp 0x74e7
jmp 0x74e7
jmp 0x74e7
jmp 0x74e7
jmp 0x74e2
movq %rax, %rbx
leaq -0xe0(%rbp), %rdi
callq 0x2100
jmp 0x74f6
movq %rax, %rbx
jmp 0x74f6
movq %rax, %rbx
leaq -0xe0(%rbp), %rdi
callq 0x11046
leaq -0xa0(%rbp), %rdi
callq 0x10f0a
movq %rbx, %rdi
callq 0x23d0