// File: dannye[P]jed/src/decoder.cpp
// Function: readFrameHeader(BitReader&, JPGImage*)
void readFrameHeader(BitReader& bitReader, JPGImage* const image) {
    // first two bytes must be 0xFF, SOI
    byte last = bitReader.readByte();
    byte current = bitReader.readByte();
    if (last != 0xFF || current != SOI) {
        std::cout << "Error - SOI invalid\n";
        image->valid = false;
        return;
    }
    last = bitReader.readByte();
    current = bitReader.readByte();

    // read markers until first scan
    while (image->valid) {
        if (!bitReader.hasBits()) {
            std::cout << "Error - File ended prematurely\n";
            image->valid = false;
            return;
        }
        if (last != 0xFF) {
            std::cout << "Error - Expected a marker\n";
            image->valid = false;
            return;
        }

        if (current == SOF0) {
            image->frameType = SOF0;
            readStartOfFrame(bitReader, image);
        }
        else if (current == SOF2) {
            image->frameType = SOF2;
            readStartOfFrame(bitReader, image);
        }
        else if (current == DQT) {
            readQuantizationTable(bitReader, image);
        }
        else if (current == DHT) {
            readHuffmanTable(bitReader, image);
        }
        else if (current == SOS) {
            // break from while loop at SOS
            break;
        }
        else if (current == DRI) {
            readRestartInterval(bitReader, image);
        }
        else if (current >= APP0 && current <= APP15) {
            readAPPN(bitReader, image);
        }
        else if (current == COM) {
            readComment(bitReader, image);
        }
        // unused markers that can be skipped
        else if ((current >= JPG0 && current <= JPG13) ||
                current == DNL ||
                current == DHP ||
                current == EXP) {
            readComment(bitReader, image);
        }
        else if (current == TEM) {
            // TEM has no size
        }
        // any number of 0xFF in a row is allowed and should be ignored
        else if (current == 0xFF) {
            current = bitReader.readByte();
            continue;
        }

        else if (current == SOI) {
            std::cout << "Error - Embedded JPGs not supported\n";
            image->valid = false;
            return;
        }
        else if (current == EOI) {
            std::cout << "Error - EOI detected before SOS\n";
            image->valid = false;
            return;
        }
        else if (current == DAC) {
            std::cout << "Error - Arithmetic Coding mode not supported\n";
            image->valid = false;
            return;
        }
        else if (current >= SOF0 && current <= SOF15) {
            std::cout << "Error - SOF marker not supported: 0x" << std::hex << (uint)current << std::dec << '\n';
            image->valid = false;
            return;
        }
        else if (current >= RST0 && current <= RST7) {
            std::cout << "Error - RSTN detected before SOS\n";
            image->valid = false;
            return;
        }
        else {
            std::cout << "Error - Unknown marker: 0x" << std::hex << (uint)current << std::dec << '\n';
            image->valid = false;
            return;
        }
        last = bitReader.readByte();
        current = bitReader.readByte();
    }
}

// Assembly:
subq $0x18, %rsp
movq %rdi, 0x10(%rsp)
movq %rsi, 0x8(%rsp)
movq 0x10(%rsp), %rdi
callq 0x7a80
movb %al, 0x7(%rsp)
movq 0x10(%rsp), %rdi
callq 0x7a80
movb %al, 0x6(%rsp)
movzbl 0x7(%rsp), %eax
cmpl $0xff, %eax
jne 0x4352
movzbl 0x6(%rsp), %eax
cmpl $0xd8, %eax
je 0x4376
movq 0x7c7f(%rip), %rdi      # 0xbfd8
leaq 0x5440(%rip), %rsi      # 0x97a0
callq 0x2110
movq 0x8(%rsp), %rax
movb $0x0, 0x2088(%rax)
jmp 0x4765
movq 0x10(%rsp), %rdi
callq 0x7a80
movb %al, 0x7(%rsp)
movq 0x10(%rsp), %rdi
callq 0x7a80
movb %al, 0x6(%rsp)
movq 0x8(%rsp), %rax
testb $0x1, 0x2088(%rax)
je 0x4765
movq 0x10(%rsp), %rdi
callq 0x7ae0
testb $0x1, %al
jne 0x43d6
movq 0x7c1f(%rip), %rdi      # 0xbfd8
leaq 0x53f5(%rip), %rsi      # 0x97b5
callq 0x2110
movq 0x8(%rsp), %rax
movb $0x0, 0x2088(%rax)
jmp 0x4765
movzbl 0x7(%rsp), %eax
cmpl $0xff, %eax
je 0x4406
movq 0x7bef(%rip), %rdi      # 0xbfd8
leaq 0x53e5(%rip), %rsi      # 0x97d5
callq 0x2110
movq 0x8(%rsp), %rax
movb $0x0, 0x2088(%rax)
jmp 0x4765
movzbl 0x6(%rsp), %eax
cmpl $0xc0, %eax
jne 0x4432
movq 0x8(%rsp), %rax
movb $-0x40, 0x2065(%rax)
movq 0x10(%rsp), %rdi
movq 0x8(%rsp), %rsi
callq 0x26a0
jmp 0x4744
movzbl 0x6(%rsp), %eax
cmpl $0xc2, %eax
jne 0x445e
movq 0x8(%rsp), %rax
movb $-0x3e, 0x2065(%rax)
movq 0x10(%rsp), %rdi
movq 0x8(%rsp), %rsi
callq 0x26a0
jmp 0x4742
movzbl 0x6(%rsp), %eax
cmpl $0xdb, %eax
jne 0x447e
movq 0x10(%rsp), %rdi
movq 0x8(%rsp), %rsi
callq 0x2c40
jmp 0x4740
movzbl 0x6(%rsp), %eax
cmpl $0xc4, %eax
jne 0x449e
movq 0x10(%rsp), %rdi
movq 0x8(%rsp), %rsi
callq 0x2e80
jmp 0x473e
movzbl 0x6(%rsp), %eax
cmpl $0xda, %eax
jne 0x44af
jmp 0x4765
movzbl 0x6(%rsp), %eax
cmpl $0xdd, %eax
jne 0x44cf
movq 0x10(%rsp), %rdi
movq 0x8(%rsp), %rsi
callq 0x3830
jmp 0x473a
movzbl 0x6(%rsp), %eax
cmpl $0xe0, %eax
jl 0x44fb
movzbl 0x6(%rsp), %eax
cmpl $0xef, %eax
jg 0x44fb
movq 0x10(%rsp), %rdi
movq 0x8(%rsp), %rsi
callq 0x38b0
jmp 0x4738
movzbl 0x6(%rsp), %eax
cmpl $0xfe, %eax
jne 0x451b
movq 0x10(%rsp), %rdi
movq 0x8(%rsp), %rsi
callq 0x3940
jmp 0x4736
movzbl 0x6(%rsp), %eax
cmpl $0xf0, %eax
jl 0x4533
movzbl 0x6(%rsp), %eax
cmpl $0xfd, %eax
jle 0x4557
movzbl 0x6(%rsp), %eax
cmpl $0xdc, %eax
je 0x4557
movzbl 0x6(%rsp), %eax
cmpl $0xde, %eax
je 0x4557
movzbl 0x6(%rsp), %eax
cmpl $0xdf, %eax
jne 0x456b
movq 0x10(%rsp), %rdi
movq 0x8(%rsp), %rsi
callq 0x3940
jmp 0x4734
movzbl 0x6(%rsp), %eax
cmpl $0x1, %eax
jne 0x457a
jmp 0x4732
movzbl 0x6(%rsp), %eax
cmpl $0xff, %eax
jne 0x4599
movq 0x10(%rsp), %rdi
callq 0x7a80
movb %al, 0x6(%rsp)
jmp 0x4392
movzbl 0x6(%rsp), %eax
cmpl $0xd8, %eax
jne 0x45c9
movq 0x7a2c(%rip), %rdi      # 0xbfd8
leaq 0x523d(%rip), %rsi      # 0x97f0
callq 0x2110
movq 0x8(%rsp), %rax
movb $0x0, 0x2088(%rax)
jmp 0x4765
movzbl 0x6(%rsp), %eax
cmpl $0xd9, %eax
jne 0x45f9
movq 0x79fc(%rip), %rdi      # 0xbfd8
leaq 0x5232(%rip), %rsi      # 0x9815
callq 0x2110
movq 0x8(%rsp), %rax
movb $0x0, 0x2088(%rax)
jmp 0x4765
movzbl 0x6(%rsp), %eax
cmpl $0xcc, %eax
jne 0x4629
movq 0x79cc(%rip), %rdi      # 0xbfd8
leaq 0x5223(%rip), %rsi      # 0x9836
callq 0x2110
movq 0x8(%rsp), %rax
movb $0x0, 0x2088(%rax)
jmp 0x4765
movzbl 0x6(%rsp), %eax
cmpl $0xc0, %eax
jl 0x469d
movzbl 0x6(%rsp), %eax
cmpl $0xcf, %eax
jg 0x469d
movq 0x7990(%rip), %rdi      # 0xbfd8
leaq 0x5215(%rip), %rsi      # 0x9864
callq 0x2110
movq %rax, %rdi
leaq 0x3442(%rip), %rsi      # 0x7aa0
callq 0x2050
movq %rax, %rdi
movzbl 0x6(%rsp), %esi
callq 0x21b0
movq %rax, %rdi
leaq 0x3446(%rip), %rsi      # 0x7ac0
callq 0x2050
movq %rax, %rdi
movl $0xa, %esi
callq 0x2160
movq 0x8(%rsp), %rax
movb $0x0, 0x2088(%rax)
jmp 0x4765
movzbl 0x6(%rsp), %eax
cmpl $0xd0, %eax
jl 0x46d9
movzbl 0x6(%rsp), %eax
cmpl $0xd7, %eax
jg 0x46d9
movq 0x791c(%rip), %rdi      # 0xbfd8
leaq 0x51c6(%rip), %rsi      # 0x9889
callq 0x2110
movq 0x8(%rsp), %rax
movb $0x0, 0x2088(%rax)
jmp 0x4765
movq 0x78f8(%rip), %rdi      # 0xbfd8
leaq 0x51c4(%rip), %rsi      # 0x98ab
callq 0x2110
movq %rax, %rdi
leaq 0x33aa(%rip), %rsi      # 0x7aa0
callq 0x2050
movq %rax, %rdi
movzbl 0x6(%rsp), %esi
callq 0x21b0
movq %rax, %rdi
leaq 0x33ae(%rip), %rsi      # 0x7ac0
callq 0x2050
movq %rax, %rdi
movl $0xa, %esi
callq 0x2160
movq 0x8(%rsp), %rax
movb $0x0, 0x2088(%rax)
jmp 0x4765
jmp 0x4734
jmp 0x4736
jmp 0x4738
jmp 0x473a
jmp 0x473c
jmp 0x473e
jmp 0x4740
jmp 0x4742
jmp 0x4744
movq 0x10(%rsp), %rdi
callq 0x7a80
movb %al, 0x7(%rsp)
movq 0x10(%rsp), %rdi
callq 0x7a80
movb %al, 0x6(%rsp)
jmp 0x4392
addq $0x18, %rsp
retq
nopw (%rax,%rax)