// File: ipatix[P]wav2agb/converter.cpp
// Function: convert(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, cmp_type)
void convert(const std::string& wav_file_str, const std::string& s_file_str,
        const std::string& sym, cmp_type ct)
{
    wav_file wf(wav_file_str);

    std::ofstream fout(s_file_str, std::ios::out);
    if (!fout.is_open()) {
        perror("ofstream");
        throw std::runtime_error("unable to open output file");
    }

    // check command line overrides
    if (wav_loop_start_override) {
        wf.loopStart = std::min(wav_loop_start, wf.loopEnd);
        wf.loopEnabled = true;
    }
    if (wav_loop_end_override) {
        wf.loopEnd = std::min(wav_loop_end, wf.loopEnd);
    }
    if (wav_tune_override) {
        wf.tuning = wav_tune;
    }
    if (wav_key_override) {
        wf.midiKey = wav_key;
    }
    if (wav_rate_override) {
        wf.sampleRate = wav_rate;
    }

    agb_out(fout, "    .section .rodata\n");
    agb_out(fout, "    .global %s\n", sym.c_str());
    agb_out(fout, "    .align  2\n\n%s:\n\n", sym.c_str());

    uint8_t fmt;
    if (ct == cmp_type::none)
        fmt = 0;
    else if (ct == cmp_type::dpcm)
        fmt = 1;
    else
        throw std::runtime_error("convert: invalid compression type");

    agb_out(fout, "    .byte   0x%X, 0x0, 0x0, 0x%X\n", fmt, wf.loopEnabled ? 0x40 : 0x0);
    double pitch;
    if (wf.midiKey == 60 && wf.tuning == 0.0)
        pitch = wf.sampleRate;
    else
        pitch = wf.sampleRate * pow(2.0, (60.0 - wf.midiKey) / 12.0 + wf.tuning / 1200.0);
    agb_out(fout, "    .word   0x%08X  @ Mid-C ~%f\n",
            static_cast<uint32_t>(pitch * 1024.0),
            pitch);
    agb_out(fout, "    .word   %u, %u\n", wf.loopStart, wf.loopEnd);

    if (ct == cmp_type::none)
        convert_uncompressed(wf, fout);
    else if (ct == cmp_type::dpcm)
        convert_dpcm(wf, fout);
    else
        throw std::runtime_error("convert: invalid compression type");

    agb_out(fout, "\n\n    .end\n");
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x4e0, %rsp            # imm = 0x4E0
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movl %ecx, -0x1c(%rbp)
movq -0x8(%rbp), %rsi
leaq -0x290(%rbp), %rdi
callq 0x6aa0
movq -0x10(%rbp), %rsi
leaq -0x490(%rbp), %rdi
movl $0x10, %edx
callq 0x3530
jmp 0x3921
leaq -0x490(%rbp), %rdi
callq 0x3220
movb %al, -0x4a9(%rbp)
jmp 0x3935
movb -0x4a9(%rbp), %al
testb $0x1, %al
jne 0x39e8
jmp 0x3945
leaq 0x86ec(%rip), %rdi      # 0xc038
callq 0x3250
jmp 0x3953
movl $0x10, %edi
callq 0x3160
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x4b8(%rbp)
leaq 0x86d0(%rip), %rsi      # 0xc041
callq 0x3110
jmp 0x3978
movq -0x4b8(%rbp), %rdi
movq 0xd672(%rip), %rsi      # 0x10ff8
movq 0xd63b(%rip), %rdx      # 0x10fc8
callq 0x34a0
jmp 0x3d70
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x498(%rbp)
movl %eax, -0x49c(%rbp)
jmp 0x3d58
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x498(%rbp)
movl %eax, -0x49c(%rbp)
jmp 0x3d4c
movq -0x4b8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x498(%rbp)
movl %eax, -0x49c(%rbp)
callq 0x3210
jmp 0x3d4c
testb $0x1, 0xd91d(%rip)      # 0x1130c
je 0x3a1a
leaq -0x38(%rbp), %rsi
leaq 0xd90c(%rip), %rdi      # 0x11308
callq 0x4610
movq %rax, -0x4c0(%rbp)
jmp 0x3a0a
movq -0x4c0(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x3c(%rbp)
movb $0x1, -0x34(%rbp)
testb $0x1, 0xd8f3(%rip)      # 0x11314
je 0x3a48
leaq -0x38(%rbp), %rsi
leaq 0xd8e2(%rip), %rdi      # 0x11310
callq 0x4610
movq %rax, -0x4c8(%rbp)
jmp 0x3a3c
movq -0x4c8(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x38(%rbp)
testb $0x1, 0xd8d1(%rip)      # 0x11320
je 0x3a5e
movsd 0xd8bf(%rip), %xmm0     # 0x11318
movsd %xmm0, -0x30(%rbp)
testb $0x1, 0xd8bd(%rip)      # 0x11322
je 0x3a70
movb 0xd8b4(%rip), %al       # 0x11321
movb %al, -0x28(%rbp)
testb $0x1, 0xd8b1(%rip)      # 0x11328
je 0x3a82
movl 0xd8a5(%rip), %eax      # 0x11324
movl %eax, -0x24(%rbp)
leaq 0x85d3(%rip), %rsi      # 0xc05c
xorl %eax, %eax
leaq -0x490(%rbp), %rdi
callq 0x3d70
jmp 0x3a99
movq -0x18(%rbp), %rdi
callq 0x3130
movq %rax, %rdx
leaq 0x85c6(%rip), %rsi      # 0xc072
xorl %eax, %eax
leaq -0x490(%rbp), %rdi
callq 0x3d70
jmp 0x3abc
movq -0x18(%rbp), %rdi
callq 0x3130
movq %rax, %rdx
leaq 0x85b3(%rip), %rsi      # 0xc082
xorl %eax, %eax
leaq -0x490(%rbp), %rdi
callq 0x3d70
jmp 0x3adf
cmpl $0x0, -0x1c(%rbp)
jne 0x3aee
movb $0x0, -0x49d(%rbp)
jmp 0x3b66
cmpl $0x1, -0x1c(%rbp)
jne 0x3afd
movb $0x1, -0x49d(%rbp)
jmp 0x3b64
movl $0x10, %edi
callq 0x3160
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x4d0(%rbp)
leaq 0x857c(%rip), %rsi      # 0xc097
callq 0x3110
jmp 0x3b22
movq -0x4d0(%rbp), %rdi
movq 0xd4c8(%rip), %rsi      # 0x10ff8
movq 0xd491(%rip), %rdx      # 0x10fc8
callq 0x34a0
jmp 0x3d70
movq -0x4d0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x498(%rbp)
movl %eax, -0x49c(%rbp)
callq 0x3210
jmp 0x3d4c
jmp 0x3b66
movzbl -0x49d(%rbp), %edx
movzbl -0x34(%rbp), %ecx
andl $0x1, %ecx
shll $0x6, %ecx
leaq 0x853b(%rip), %rsi      # 0xc0b9
xorl %eax, %eax
leaq -0x490(%rbp), %rdi
callq 0x3d70
jmp 0x3b8e
movzbl -0x28(%rbp), %eax
cmpl $0x3c, %eax
jne 0x3bb9
movsd -0x30(%rbp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x3bb9
jp 0x3bb9
movl -0x24(%rbp), %eax
cvtsi2sd %rax, %xmm0
movsd %xmm0, -0x4a8(%rbp)
jmp 0x3c22
movl -0x24(%rbp), %eax
cvtsi2sd %rax, %xmm0
movsd %xmm0, -0x4d8(%rbp)
movzbl -0x28(%rbp), %eax
cvtsi2sd %eax, %xmm0
movsd 0x8447(%rip), %xmm1     # 0xc020
subsd %xmm0, %xmm1
movsd 0x8433(%rip), %xmm0     # 0xc018
divsd %xmm0, %xmm1
movsd -0x30(%rbp), %xmm0
movsd 0x841a(%rip), %xmm2     # 0xc010
divsd %xmm2, %xmm0
addsd %xmm0, %xmm1
movsd 0x8402(%rip), %xmm0     # 0xc008
callq 0x34d0
movaps %xmm0, %xmm1
movsd -0x4d8(%rbp), %xmm0
mulsd %xmm1, %xmm0
movsd %xmm0, -0x4a8(%rbp)
movsd -0x4a8(%rbp), %xmm0
movsd 0x83f6(%rip), %xmm2     # 0xc028
movaps %xmm0, %xmm1
mulsd %xmm2, %xmm1
cvttsd2si %xmm1, %rax
movl %eax, %edx
leaq 0x8494(%rip), %rsi      # 0xc0db
leaq -0x490(%rbp), %rdi
movb $0x1, %al
callq 0x3d70
jmp 0x3c57
movl -0x3c(%rbp), %edx
movl -0x38(%rbp), %ecx
leaq 0x8498(%rip), %rsi      # 0xc0fc
xorl %eax, %eax
leaq -0x490(%rbp), %rdi
callq 0x3d70
jmp 0x3c74
cmpl $0x0, -0x1c(%rbp)
jne 0x3c94
leaq -0x290(%rbp), %rdi
leaq -0x490(%rbp), %rsi
callq 0x3e50
jmp 0x3c8f
jmp 0x3d14
cmpl $0x1, -0x1c(%rbp)
jne 0x3cb1
leaq -0x290(%rbp), %rdi
leaq -0x490(%rbp), %rsi
callq 0x3f50
jmp 0x3caf
jmp 0x3d12
movl $0x10, %edi
callq 0x3160
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x4e0(%rbp)
leaq 0x83c8(%rip), %rsi      # 0xc097
callq 0x3110
jmp 0x3cd6
movq -0x4e0(%rbp), %rdi
movq 0xd314(%rip), %rsi      # 0x10ff8
movq 0xd2dd(%rip), %rdx      # 0x10fc8
callq 0x34a0
jmp 0x3d70
movq -0x4e0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x498(%rbp)
movl %eax, -0x49c(%rbp)
callq 0x3210
jmp 0x3d4c
jmp 0x3d14
leaq 0x83f5(%rip), %rsi      # 0xc110
xorl %eax, %eax
leaq -0x490(%rbp), %rdi
callq 0x3d70
jmp 0x3d2b
leaq -0x490(%rbp), %rdi
callq 0x3400
leaq -0x290(%rbp), %rdi
callq 0x8480
addq $0x4e0, %rsp            # imm = 0x4E0
popq %rbp
retq
leaq -0x490(%rbp), %rdi
callq 0x3400
leaq -0x290(%rbp), %rdi
callq 0x8480
movq -0x498(%rbp), %rdi
callq 0x34e0