// File: /workspace/github_cpp_makefile_star2_O2/dannye[P]jed/src/decoder.cpp
// Function: readStartOfScan(BitReader&, JPGImage*)
void readStartOfScan(BitReader& bitReader, JPGImage* const image) {
    std::cout << "Reading SOS Marker\n";
    if (image->numComponents == 0) {
        std::cout << "Error - SOS detected before SOF\n";
        image->valid = false;
        return;
    }

    uint length = bitReader.readWord();

    for (uint i = 0; i < image->numComponents; ++i) {
        image->colorComponents[i].usedInScan = false;
    }

    // the number of components in the next scan might not be all
    //   components in the image
    image->componentsInScan = bitReader.readByte();
    if (image->componentsInScan == 0) {
        std::cout << "Error - Scan must include at least 1 component\n";
        image->valid = false;
        return;
    }
    for (uint i = 0; i < image->componentsInScan; ++i) {
        byte componentID = bitReader.readByte();
        // component IDs are usually 1, 2, 3 but rarely can be seen as 0, 1, 2
        if (image->zeroBased) {
            componentID += 1;
        }
        if (componentID == 0 || componentID > image->numComponents) {
            std::cout << "Error - Invalid color component ID: " << (uint)componentID << '\n';
            image->valid = false;
            return;
        }
        ColorComponent& component = image->colorComponents[componentID - 1];
        if (!component.usedInFrame) {
            std::cout << "Error - Invalid color component ID: " << (uint)componentID << '\n';
            image->valid = false;
            return;
        }
        if (component.usedInScan) {
            std::cout << "Error - Duplicate color component ID: " << (uint)componentID << '\n';
            image->valid = false;
            return;
        }
        component.usedInScan = true;

        byte huffmanTableIDs = bitReader.readByte();
        component.huffmanDCTableID = huffmanTableIDs >> 4;
        component.huffmanACTableID = huffmanTableIDs & 0x0F;
        if (component.huffmanDCTableID > 3) {
            std::cout << "Error - Invalid Huffman DC table ID: " << (uint)component.huffmanDCTableID << '\n';
            image->valid = false;
            return;
        }
        if (component.huffmanACTableID > 3) {
            std::cout << "Error - Invalid Huffman AC table ID: " << (uint)component.huffmanACTableID << '\n';
            image->valid = false;
            return;
        }
    }

    image->startOfSelection = bitReader.readByte();
    image->endOfSelection = bitReader.readByte();
    byte successiveApproximation = bitReader.readByte();
    image->successiveApproximationHigh = successiveApproximation >> 4;
    image->successiveApproximationLow = successiveApproximation & 0x0F;

    if (image->frameType == SOF0) {
        // Baseline JPGs don't use spectral selection or successive approximtion
        if (image->startOfSelection != 0 || image->endOfSelection != 63) {
            std::cout << "Error - Invalid spectral selection\n";
            image->valid = false;
            return;
        }
        if (image->successiveApproximationHigh != 0 || image->successiveApproximationLow != 0) {
            std::cout << "Error - Invalid successive approximation\n";
            image->valid = false;
            return;
        }
    }
    else if (image->frameType == SOF2) {
        if (image->startOfSelection > image->endOfSelection) {
            std::cout << "Error - Invalid spectral selection (start greater than end)\n";
            image->valid = false;
            return;
        }
        if (image->endOfSelection > 63) {
            std::cout << "Error - Invalid spectral selection (end greater than 63)\n";
            image->valid = false;
            return;
        }
        if (image->startOfSelection == 0 && image->endOfSelection != 0) {
            std::cout << "Error - Invalid spectral selection (contains DC and AC)\n";
            image->valid = false;
            return;
        }
        if (image->startOfSelection != 0 && image->componentsInScan != 1) {
            std::cout << "Error - Invalid spectral selection (AC scan contains multiple components)\n";
            image->valid = false;
            return;
        }
        if (image->successiveApproximationHigh != 0 &&
            image->successiveApproximationLow != image->successiveApproximationHigh - 1) {
            std::cout << "Error - Invalid successive approximation\n";
            image->valid = false;
            return;
        }
    }

    for (uint i = 0; i < image->numComponents; ++i) {
        const ColorComponent& component = image->colorComponents[i];
        if (image->colorComponents[i].usedInScan) {
            if (image->quantizationTables[component.quantizationTableID].set == false) {
                std::cout << "Error - Color component using uninitialized quantization table\n";
                image->valid = false;
                return;
            }
            if (image->startOfSelection == 0) {
                if (image->huffmanDCTables[component.huffmanDCTableID].set == false) {
                    std::cout << "Error - Color component using uninitialized Huffman DC table\n";
                    image->valid = false;
                    return;
                }
            }
            if (image->endOfSelection > 0) {
                if (image->huffmanACTables[component.huffmanACTableID].set == false) {
                    std::cout << "Error - Color component using uninitialized Huffman AC table\n";
                    image->valid = false;
                    return;
                }
            }
        }
    }

    if (length - 6 - (2 * image->componentsInScan) != 0) {
        std::cout << "Error - SOS invalid\n";
        image->valid = false;
        return;
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rsi, %rbx
movq %rdi, %r14
movq 0x665c(%rip), %rdi      # 0x8fd8
leaq 0x3934(%rip), %rsi      # 0x62b7
callq 0x20e0
cmpb $0x0, 0x2070(%rbx)
je 0x2a8b
movq %r14, %rdi
callq 0x4fd4
movl %eax, %ebp
movzbl 0x2070(%rbx), %eax
leaq 0x2050(%rbx), %r13
imulq $0x7, %rax, %rax
xorl %ecx, %ecx
cmpq %rcx, %rax
je 0x29c6
movb $0x0, 0x2056(%rbx,%rcx)
addq $0x7, %rcx
jmp 0x29b3
movq %r14, %rdi
callq 0x5000
movb %al, 0x2072(%rbx)
testb %al, %al
je 0x2a9b
movl %ebp, 0x4(%rsp)
pushq $-0x1
popq %rbp
movzbl 0x2072(%rbx), %r15d
movq %r14, %rdi
callq 0x5000
incl %ebp
cmpl %r15d, %ebp
jae 0x2ab3
addb 0x2071(%rbx), %al
je 0x2b3e
movzbl %al, %r12d
cmpb 0x2070(%rbx), %r12b
ja 0x2b41
leal -0x1(%r12), %eax
imulq $0x7, %rax, %r15
cmpb $0x0, 0x5(%r13,%r15)
je 0x2b41
addq %r13, %r15
cmpb $0x1, 0x6(%r15)
je 0x2b51
movb $0x1, 0x6(%r15)
movq %r14, %rdi
callq 0x5000
movl %eax, %ecx
shrb $0x4, %cl
movb %cl, 0x3(%r15)
movl %eax, %ecx
andb $0xf, %cl
movb %cl, 0x4(%r15)
cmpb $0x40, %al
jae 0x2b6c
cmpb $0x4, %cl
jb 0x29e3
movq 0x6563(%rip), %rdi      # 0x8fd8
leaq 0x38eb(%rip), %rsi      # 0x6367
callq 0x20e0
movzbl 0x4(%r15), %esi
jmp 0x2b84
movq 0x6546(%rip), %rdi      # 0x8fd8
leaq 0x3832(%rip), %rsi      # 0x62cb
jmp 0x2aa9
movq 0x6536(%rip), %rdi      # 0x8fd8
leaq 0x3843(%rip), %rsi      # 0x62ec
callq 0x20e0
jmp 0x2b97
movb %al, 0x2073(%rbx)
movq %r14, %rdi
callq 0x5000
movb %al, 0x2074(%rbx)
movq %r14, %rdi
callq 0x5000
movl %eax, %ecx
shrb $0x4, %cl
movb %cl, 0x2075(%rbx)
movl %eax, %edx
andb $0xf, %dl
movb %dl, 0x2076(%rbx)
movzbl 0x2065(%rbx), %esi
cmpl $0xc2, %esi
je 0x2bad
cmpl $0xc0, %esi
movl 0x4(%rsp), %r9d
jne 0x2c41
cmpb $0x0, 0x2073(%rbx)
jne 0x2bd8
cmpb $0x3f, 0x2074(%rbx)
jne 0x2bd8
testb %al, %al
je 0x2c41
movq 0x64a6(%rip), %rdi      # 0x8fd8
leaq 0x3878(%rip), %rsi      # 0x63b1
jmp 0x2aa9
xorl %r12d, %r12d
movq 0x6490(%rip), %rdi      # 0x8fd8
leaq 0x37cd(%rip), %rsi      # 0x631c
jmp 0x2b5f
movq 0x6480(%rip), %rdi      # 0x8fd8
leaq 0x362b(%rip), %rsi      # 0x618a
callq 0x20e0
movq %rax, %rdi
movq %r12, %rsi
jmp 0x2b87
movq 0x6465(%rip), %rdi      # 0x8fd8
leaq 0x37c7(%rip), %rsi      # 0x6341
callq 0x20e0
movzbl 0x3(%r15), %esi
movq %rax, %rdi
callq 0x20a0
pushq $0xa
popq %rsi
movq %rax, %rdi
callq 0x2120
movb $0x0, 0x2088(%rbx)
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movb 0x2073(%rbx), %sil
movb 0x2074(%rbx), %dil
cmpb %dil, %sil
movl 0x4(%rsp), %r9d
jbe 0x2beb
movq 0x640c(%rip), %rdi      # 0x8fd8
leaq 0x3808(%rip), %rsi      # 0x63db
jmp 0x2aa9
movq 0x63f9(%rip), %rdi      # 0x8fd8
leaq 0x37a7(%rip), %rsi      # 0x638d
jmp 0x2aa9
cmpb $0x40, %dil
jb 0x2c04
movq 0x63e0(%rip), %rdi      # 0x8fd8
leaq 0x3819(%rip), %rsi      # 0x6418
jmp 0x2aa9
testb %sil, %sil
setne %r8b
testb %dil, %dil
sete %dil
orb %r8b, %dil
je 0x2d21
testb %sil, %sil
je 0x2c2d
cmpb $0x1, 0x2072(%rbx)
jne 0x2d47
cmpb $0x10, %al
jb 0x2c41
movzbl %cl, %eax
movzbl %dl, %ecx
decl %eax
cmpl %ecx, %eax
jne 0x2b2b
movzbl 0x2070(%rbx), %edx
leaq 0x410(%rbx), %rax
leaq 0x1230(%rbx), %rcx
imulq $0x7, %rdx, %rdx
xorl %esi, %esi
cmpq %rsi, %rdx
je 0x2cd2
cmpb $0x1, 0x2056(%rbx,%rsi)
jne 0x2ccc
movzbl 0x2052(%rbx,%rsi), %edi
imulq $0x104, %rdi, %rdi      # imm = 0x104
cmpb $0x0, 0x100(%rbx,%rdi)
je 0x2cfb
cmpb $0x0, 0x2073(%rbx)
jne 0x2caa
movzbl 0x2053(%rbx,%rsi), %edi
imulq $0x388, %rdi, %rdi      # imm = 0x388
cmpb $0x0, 0x384(%rax,%rdi)
je 0x2d34
cmpb $0x0, 0x2074(%rbx)
je 0x2ccc
movzbl 0x2054(%rbx,%rsi), %edi
imulq $0x388, %rdi, %rdi      # imm = 0x388
cmpb $0x0, 0x384(%rcx,%rdi)
je 0x2d0e
addq $0x7, %rsi
jmp 0x2c5c
addl $-0x6, %r9d
movzbl 0x2072(%rbx), %eax
addl %eax, %eax
cmpl %eax, %r9d
je 0x2b9e
movq 0x62e9(%rip), %rdi      # 0x8fd8
leaq 0x389c(%rip), %rsi      # 0x6592
jmp 0x2aa9
movq 0x62d6(%rip), %rdi      # 0x8fd8
leaq 0x37cd(%rip), %rsi      # 0x64d6
jmp 0x2aa9
movq 0x62c3(%rip), %rdi      # 0x8fd8
leaq 0x3838(%rip), %rsi      # 0x6554
jmp 0x2aa9
movq 0x62b0(%rip), %rdi      # 0x8fd8
leaq 0x3723(%rip), %rsi      # 0x6452
jmp 0x2aa9
movq 0x629d(%rip), %rdi      # 0x8fd8
leaq 0x37d4(%rip), %rsi      # 0x6516
jmp 0x2aa9
movq 0x628a(%rip), %rdi      # 0x8fd8
leaq 0x3736(%rip), %rsi      # 0x648b
jmp 0x2aa9