// File: qhan1028[P]JPEG-Decoder/jpeg-decoder.cpp
// Function: main
int main(int argc, char* argv[]) {
    if (argc < 2) {
        cout << "[Error] usage: ./jpeg-decoder [filename].jpg" << endl;
        return -1;
    }

    /* parse filename */
    string filename;
    for (int i = 0; i < argc; i++) {
        if (strcmp(argv[i], "--debug") == 0)
            debug = true;
        else
            filename = argv[i];
    }

    /* open jpeg */
    ifstream jpegfile;
    jpegfile.open(filename, ifstream::binary);
    if (!jpegfile.is_open()) {
        cout << "[Error] fail to open file: " << filename << endl;
        return -2;
    }

    /* read first tag */
    if (process_SOI(jpegfile))
        return -3;

    /* initialize */
    qtable_t qtable = init_qtable();
    sof_t sof;
    htable_t* htable = init_htable();
    sos_t sos;
    image_t rgb;

    char c1, c2;
    bool eoi = false; // end of image

    while(!eoi) {
        jpegfile.read(&c1, 1);
        jpegfile.read(&c2, 1);

        if (to_uint(c1) == TAG && to_uint(c2) != TAG) {

            unsigned int opt = to_uint(c2);

            switch(opt) {
                case DQT:
                    process_DQT(jpegfile, qtable);
                    break;
                
                case SOF0:
                    process_SOF0(jpegfile, sof);
                    break;
                
                case DHT:
                    process_DHT(jpegfile, htable);
                    break;
                
                case SOS:
                    process_SOS(jpegfile, sos);
                    if (debug) {
                        print_DQT(qtable);
                        print_SOF(sof);
                        print_DHT(htable);
                        print_SOS(sos);
                    }
                    rgb = process_scan(jpegfile, qtable, sof, htable, sos);
                    break;
                
                case EOI:
                    process_EOI(eoi);
                    break;
                
                default:
                    process_other(jpegfile, opt);
            }
        }
    }

    jpegfile.close();

    /* output bitmap */
    to_bitmap(filename, rgb, sof);

    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x330, %rsp            # imm = 0x330
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
cmpl $0x2, -0x8(%rbp)
jge 0x5d7d
movq 0xa27a(%rip), %rdi      # 0xffd0
leaq 0x55e9(%rip), %rsi      # 0xb346
callq 0x21b0
movq %rax, %rdi
movq 0xa254(%rip), %rsi      # 0xffc0
callq 0x21f0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x61b7
leaq -0x30(%rbp), %rdi
callq 0x22a0
movl $0x0, -0x34(%rbp)
movl -0x34(%rbp), %eax
cmpl -0x8(%rbp), %eax
jge 0x5df2
movq -0x10(%rbp), %rax
movslq -0x34(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
leaq 0x55cb(%rip), %rsi      # 0xb373
callq 0x22b0
cmpl $0x0, %eax
jne 0x5dbb
movb $0x1, 0xa461(%rip)      # 0x1021a
jmp 0x5de5
movq -0x10(%rbp), %rax
movslq -0x34(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
leaq -0x30(%rbp), %rdi
callq 0x2280
jmp 0x5dd2
jmp 0x5de5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x61ac
jmp 0x5de7
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x5d8d
leaq -0x250(%rbp), %rdi
callq 0x2220
jmp 0x5e00
leaq -0x250(%rbp), %rdi
leaq -0x30(%rbp), %rsi
movl $0x4, %edx
callq 0x2160
jmp 0x5e17
leaq -0x250(%rbp), %rdi
callq 0x2300
movb %al, -0x2d9(%rbp)
jmp 0x5e2b
movb -0x2d9(%rbp), %al
testb $0x1, %al
jne 0x5ea8
jmp 0x5e37
movq 0xa192(%rip), %rdi      # 0xffd0
leaq 0x5536(%rip), %rsi      # 0xb37b
callq 0x21b0
movq %rax, -0x2e8(%rbp)
jmp 0x5e53
movq -0x2e8(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0x2180
movq %rax, -0x2f0(%rbp)
jmp 0x5e6c
movq -0x2f0(%rbp), %rdi
movq 0xa146(%rip), %rsi      # 0xffc0
callq 0x21f0
jmp 0x5e81
movl $0xfffffffe, -0x4(%rbp) # imm = 0xFFFFFFFE
movl $0x1, -0x254(%rbp)
jmp 0x6189
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x61a0
leaq -0x250(%rbp), %rdi
callq 0x3100
movb %al, -0x2f1(%rbp)
jmp 0x5ebc
movb -0x2f1(%rbp), %al
testb $0x1, %al
jne 0x5ec8
jmp 0x5ede
movl $0xfffffffd, -0x4(%rbp) # imm = 0xFFFFFFFD
movl $0x1, -0x254(%rbp)
jmp 0x6189
callq 0x31c0
movq %rax, -0x300(%rbp)
jmp 0x5eec
movq -0x300(%rbp), %rax
movq %rax, -0x260(%rbp)
callq 0x3900
movq %rax, -0x308(%rbp)
jmp 0x5f08
movq -0x308(%rbp), %rax
movq %rax, -0x288(%rbp)
movb $0x0, -0x2b3(%rbp)
movb -0x2b3(%rbp), %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x5f2e
jmp 0x6114
leaq -0x250(%rbp), %rdi
leaq -0x2b1(%rbp), %rsi
movl $0x1, %edx
callq 0x2230
jmp 0x5f48
leaq -0x250(%rbp), %rdi
leaq -0x2b2(%rbp), %rsi
movl $0x1, %edx
callq 0x2230
jmp 0x5f62
movsbl -0x2b1(%rbp), %edi
callq 0x6210
movl %eax, -0x30c(%rbp)
jmp 0x5f76
movl -0x30c(%rbp), %eax
cmpl $0xff, %eax
jne 0x610f
movsbl -0x2b2(%rbp), %edi
callq 0x6210
movl %eax, -0x310(%rbp)
jmp 0x5f9b
movl -0x310(%rbp), %eax
cmpl $0xff, %eax
je 0x610f
movsbl -0x2b2(%rbp), %edi
callq 0x6210
movl %eax, -0x314(%rbp)
jmp 0x5fc0
movl -0x314(%rbp), %eax
movl %eax, -0x2b8(%rbp)
movl -0x2b8(%rbp), %eax
addl $0xffffff40, %eax       # imm = 0xFFFFFF40
movl %eax, %ecx
movq %rcx, -0x320(%rbp)
subl $0x1b, %eax
ja 0x60f7
movq -0x320(%rbp), %rax
leaq 0x5071(%rip), %rcx      # 0xb068
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x260(%rbp), %rsi
leaq -0x250(%rbp), %rdi
callq 0x3350
jmp 0x6015
jmp 0x610d
leaq -0x250(%rbp), %rdi
leaq -0x280(%rbp), %rsi
callq 0x3660
jmp 0x602f
jmp 0x610d
movq -0x288(%rbp), %rsi
leaq -0x250(%rbp), %rdi
callq 0x3ab0
jmp 0x6049
jmp 0x610d
leaq -0x250(%rbp), %rdi
leaq -0x2a8(%rbp), %rsi
callq 0x3eb0
jmp 0x6063
testb $0x1, 0xa1b0(%rip)      # 0x1021a
je 0x60a6
movq -0x260(%rbp), %rdi
callq 0x3220
jmp 0x607a
leaq -0x280(%rbp), %rdi
callq 0x3490
jmp 0x6088
movq -0x288(%rbp), %rdi
callq 0x3970
jmp 0x6096
leaq -0x2a8(%rbp), %rdi
callq 0x3cf0
jmp 0x60a4
jmp 0x60a6
movq -0x260(%rbp), %rsi
movq -0x288(%rbp), %rcx
leaq -0x250(%rbp), %rdi
leaq -0x280(%rbp), %rdx
leaq -0x2a8(%rbp), %r8
callq 0x4460
movq %rax, -0x328(%rbp)
jmp 0x60d7
movq -0x328(%rbp), %rax
movq %rax, -0x2b0(%rbp)
jmp 0x610d
leaq -0x2b3(%rbp), %rdi
callq 0x5be0
jmp 0x60f5
jmp 0x610d
movl -0x2b8(%rbp), %esi
leaq -0x250(%rbp), %rdi
callq 0x5c30
jmp 0x610b
jmp 0x610d
jmp 0x610f
jmp 0x5f1d
leaq -0x250(%rbp), %rdi
callq 0x2060
jmp 0x6122
leaq -0x2d8(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0x20d0
jmp 0x6134
movq -0x2b0(%rbp), %rsi
leaq -0x2d8(%rbp), %rdi
leaq -0x280(%rbp), %rdx
callq 0x42b0
jmp 0x6150
leaq -0x2d8(%rbp), %rdi
callq 0x2120
movl $0x0, -0x4(%rbp)
movl $0x1, -0x254(%rbp)
jmp 0x6189
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x2d8(%rbp), %rdi
callq 0x2120
jmp 0x61a0
leaq -0x250(%rbp), %rdi
callq 0x2080
leaq -0x30(%rbp), %rdi
callq 0x2120
jmp 0x61b7
leaq -0x250(%rbp), %rdi
callq 0x2080
leaq -0x30(%rbp), %rdi
callq 0x2120
jmp 0x61c3
movl -0x4(%rbp), %eax
addq $0x330, %rsp            # imm = 0x330
popq %rbp
retq
movq -0x40(%rbp), %rdi
callq 0x2340
nopl (%rax)