// File: /workspace/github_c_makefile_star2_O3/KhronosGroup[P]dfdutils/printdfd.c
// Function: printDFD
void printDFD(uint32_t *DFD, uint32_t dataSize)
{
#define PRINT_ENUM(VALUE, TO_STRING_FN) {                        \
        int value = VALUE;                                       \
        const char* str = TO_STRING_FN(value);                   \
        if (str)                                                 \
            printf("%s", str);                                   \
        else                                                     \
            printf("%u", value);                                 \
    }

    const uint32_t sizeof_dfdTotalSize = sizeof(uint32_t);
    const uint32_t sizeof_DFDBHeader = sizeof(uint32_t) * 2;
    const uint32_t sizeof_BDFD = sizeof(uint32_t) * KHR_DF_WORD_SAMPLESTART;
    const uint32_t sizeof_BDFDSample = sizeof(uint32_t) * KHR_DF_WORD_SAMPLEWORDS;

    uint32_t dfdTotalSize = dataSize >= sizeof_dfdTotalSize ? DFD[0] : 0;
    uint32_t remainingSize = dfdTotalSize < dataSize ? dfdTotalSize : dataSize;
    if (remainingSize < sizeof_dfdTotalSize)
        return; // Invalid DFD: dfdTotalSize must be present

    uint32_t* block = DFD + 1;
    remainingSize -= sizeof_dfdTotalSize;

    printf("DFD total bytes: %u\n", dfdTotalSize);

    for (int i = 0; i < MAX_NUM_DFD_BLOCKS; ++i) { // At most only iterate MAX_NUM_DFD_BLOCKS block
        if (remainingSize < sizeof_DFDBHeader)
            break; // Invalid DFD: Missing or partial block header

        const khr_df_vendorid_e vendorID = KHR_DFDVAL(block, VENDORID);
        const khr_df_khr_descriptortype_e descriptorType = KHR_DFDVAL(block, DESCRIPTORTYPE);
        const khr_df_versionnumber_e versionNumber = KHR_DFDVAL(block, VERSIONNUMBER);
        const uint32_t blockSize = KHR_DFDVAL(block, DESCRIPTORBLOCKSIZE);

        printf("Vendor ID: ");
        PRINT_ENUM(vendorID, dfdToStringVendorID);
        printf("\nDescriptor type: ");
        PRINT_ENUM(descriptorType, dfdToStringDescriptorType);
        printf("\nVersion: ");
        PRINT_ENUM(versionNumber, dfdToStringVersionNumber);
        printf("\nDescriptor block size: %u", blockSize);
        printf("\n");

        if (vendorID == KHR_DF_VENDORID_KHRONOS && descriptorType == KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT) {
            if (remainingSize < sizeof_BDFD)
                break; // Invalid DFD: Missing or partial basic DFD block

            const int model = KHR_DFDVAL(block, MODEL);

            khr_df_flags_e flags = KHR_DFDVAL(block, FLAGS);
            printf("Flags: 0x%X (", flags);
            printFlagBits(flags, dfdToStringFlagsBit);
            printf(")\nTransfer: ");
            PRINT_ENUM(KHR_DFDVAL(block, TRANSFER), dfdToStringTransferFunction);
            printf("\nPrimaries: ");
            PRINT_ENUM(KHR_DFDVAL(block, PRIMARIES), dfdToStringColorPrimaries);
            printf("\nModel: ");
            PRINT_ENUM(model, dfdToStringColorModel);
            printf("\n");

            printf("Dimensions: %u, %u, %u, %u\n",
                   KHR_DFDVAL(block, TEXELBLOCKDIMENSION0) + 1,
                   KHR_DFDVAL(block, TEXELBLOCKDIMENSION1) + 1,
                   KHR_DFDVAL(block, TEXELBLOCKDIMENSION2) + 1,
                   KHR_DFDVAL(block, TEXELBLOCKDIMENSION3) + 1);
            printf("Plane bytes: %u, %u, %u, %u, %u, %u, %u, %u\n",
                   KHR_DFDVAL(block, BYTESPLANE0),
                   KHR_DFDVAL(block, BYTESPLANE1),
                   KHR_DFDVAL(block, BYTESPLANE2),
                   KHR_DFDVAL(block, BYTESPLANE3),
                   KHR_DFDVAL(block, BYTESPLANE4),
                   KHR_DFDVAL(block, BYTESPLANE5),
                   KHR_DFDVAL(block, BYTESPLANE6),
                   KHR_DFDVAL(block, BYTESPLANE7));

            int samples = (blockSize - sizeof_BDFD) / sizeof_BDFDSample;
            if (samples > MAX_NUM_BDFD_SAMPLES)
                samples = MAX_NUM_BDFD_SAMPLES; // Too many BDFD samples
            for (int sample = 0; sample < samples; ++sample) {
                if (remainingSize < sizeof_BDFD + (sample + 1) * sizeof_BDFDSample)
                    break; // Invalid DFD: Missing or partial basic DFD sample

                khr_df_model_channels_e channelType = KHR_DFDSVAL(block, sample, CHANNELID);
                printf("Sample %u:\n", sample);

                khr_df_sample_datatype_qualifiers_e qualifiers = KHR_DFDSVAL(block, sample, QUALIFIERS);
                printf("    Qualifiers: 0x%X (", qualifiers);
                printFlagBits(qualifiers, dfdToStringSampleDatatypeQualifiers);
                printf(")\n");
                printf("    Channel Type: 0x%X", channelType);
                {
                    const char* str = dfdToStringChannelId(model, channelType);
                    if (str)
                        printf(" (%s)\n", str);
                    else
                        printf(" (%u)\n", channelType);
                }
                printf("    Length: %u bits Offset: %u\n",
                       KHR_DFDSVAL(block, sample, BITLENGTH) + 1,
                       KHR_DFDSVAL(block, sample, BITOFFSET));
                printf("    Position: %u, %u, %u, %u\n",
                       KHR_DFDSVAL(block, sample, SAMPLEPOSITION0),
                       KHR_DFDSVAL(block, sample, SAMPLEPOSITION1),
                       KHR_DFDSVAL(block, sample, SAMPLEPOSITION2),
                       KHR_DFDSVAL(block, sample, SAMPLEPOSITION3));
                printf("    Lower: 0x%08x\n    Upper: 0x%08x\n",
                       KHR_DFDSVAL(block, sample, SAMPLELOWER),
                       KHR_DFDSVAL(block, sample, SAMPLEUPPER));
            }
        } else if (vendorID == KHR_DF_VENDORID_KHRONOS && descriptorType == KHR_DF_KHR_DESCRIPTORTYPE_ADDITIONAL_DIMENSIONS) {
            // TODO: Implement DFD print for ADDITIONAL_DIMENSIONS
        } else if (vendorID == KHR_DF_VENDORID_KHRONOS && descriptorType == KHR_DF_KHR_DESCRIPTORTYPE_ADDITIONAL_PLANES) {
            // TODO: Implement DFD print for ADDITIONAL_PLANES
        } else {
            printf("Unknown block\n");
        }

        const uint32_t advance = sizeof_DFDBHeader > blockSize ? sizeof_DFDBHeader : blockSize;
        if (advance > remainingSize)
            break;
        remainingSize -= advance;
        block += advance / 4;
    }
#undef PRINT_ENUM
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movl %esi, %r14d
movq %rdi, %rbp
xorl %esi, %esi
cmpl $0x4, %r14d
jb 0x2d88
movl (%rbp), %esi
cmpl %r14d, %esi
cmovbl %esi, %r14d
cmpl $0x4, %r14d
jb 0x2dad
addl $-0x4, %r14d
leaq 0x2c3a(%rip), %rdi      # 0x59da
xorl %eax, %eax
callq 0x1050
cmpl $0x8, %r14d
jae 0x2dbc
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
addq $0x4, %rbp
leaq 0x303f(%rip), %r13      # 0x5e06
xorl %ebx, %ebx
movq %rbp, %rax
movl (%rbp), %ebp
movq %rax, (%rsp)
movl 0x4(%rax), %r12d
leaq 0x2c11(%rip), %rdi      # 0x59ef
xorl %eax, %eax
callq 0x1050
movl %ebp, %r15d
andl $0x1ffff, %r15d         # imm = 0x1FFFF
movl %ebx, 0x10(%rsp)
je 0x2e08
leaq 0x2c35(%rip), %rdi      # 0x5a31
movl %r15d, %esi
xorl %eax, %eax
callq 0x1050
jmp 0x2e1d
leaq 0x2f12(%rip), %rdi      # 0x5d21
leaq 0x19fa(%rip), %rsi      # 0x4810
xorl %eax, %eax
callq 0x1050
movl %ebp, %ebx
shrl $0x11, %ebx
leaq 0x2bd2(%rip), %rdi      # 0x59fb
xorl %eax, %eax
callq 0x1050
leaq 0x19f1(%rip), %rsi      # 0x4828
testl %ebx, %ebx
je 0x2e5b
cmpl $0x6002, %ebx           # imm = 0x6002
je 0x2e54
cmpl $0x6001, %ebx           # imm = 0x6001
jne 0x2e6b
leaq 0x19fc(%rip), %rsi      # 0x484e
jmp 0x2e5b
leaq 0x1a1f(%rip), %rsi      # 0x487a
leaq 0x2ebf(%rip), %rdi      # 0x5d21
xorl %eax, %eax
callq 0x1050
jmp 0x2e7b
leaq 0x2bbf(%rip), %rdi      # 0x5a31
movl %ebx, %esi
xorl %eax, %eax
callq 0x1050
leaq 0x2b8c(%rip), %rdi      # 0x5a0e
xorl %eax, %eax
callq 0x1050
cmpw $0x2, %r12w
ja 0x2eb1
movl %r12d, %eax
andl $0x3, %eax
leaq 0x4f43(%rip), %rcx      # 0x7de0
movq (%rcx,%rax,8), %rsi
leaq 0x2e79(%rip), %rdi      # 0x5d21
xorl %eax, %eax
callq 0x1050
jmp 0x2ec3
movzwl %r12w, %esi
leaq 0x2b75(%rip), %rdi      # 0x5a31
xorl %eax, %eax
callq 0x1050
shrl $0x10, %r12d
leaq 0x2b4b(%rip), %rdi      # 0x5a19
movq %r12, 0x18(%rsp)
movl %r12d, %esi
xorl %eax, %eax
callq 0x1050
movl $0xa, %edi
callq 0x1030
testl %ebp, %ebp
movl %r14d, 0xc(%rsp)
je 0x2f1f
testl %r15d, %r15d
sete %al
addl $0xffff9fff, %ebx       # imm = 0xFFFF9FFF
cmpl $0x2, %ebx
setb %cl
testb %cl, %al
movq (%rsp), %rbp
jne 0x32f4
leaq 0x2f11(%rip), %rdi      # 0x5e26
callq 0x1040
jmp 0x32f4
cmpl $0x18, %r14d
movq (%rsp), %rax
jb 0x2dad
movl 0x8(%rax), %r14d
movl %r14d, %ebx
shrl $0x18, %ebx
xorl %ebp, %ebp
leaq 0x2af4(%rip), %rdi      # 0x5a34
movl %ebx, %esi
xorl %eax, %eax
callq 0x1050
movb $0x1, %r15b
movl $0x1, %edx
movl %ebp, %ecx
shll %cl, %edx
testb $0x1, %r15b
movq %r13, %rsi
leaq 0x2b8b(%rip), %rax      # 0x5aee
cmovneq %rax, %rsi
testl %ebp, %ebp
je 0x2f82
testl %ebx, %edx
je 0x2fa7
xorl %r15d, %r15d
leaq 0x2c78(%rip), %rdi      # 0x5bf1
xorl %eax, %eax
callq 0x1050
jmp 0x2fa7
testl %ebx, %edx
leaq 0x196a(%rip), %rdx      # 0x48f5
leaq 0x1983(%rip), %rax      # 0x4915
cmoveq %rax, %rdx
xorl %r15d, %r15d
leaq 0x2e69(%rip), %rdi      # 0x5e09
xorl %eax, %eax
callq 0x1050
incl %ebp
cmpl $0x20, %ebp
jne 0x2f4c
leaq 0x2a8d(%rip), %rdi      # 0x5a42
xorl %eax, %eax
callq 0x1050
movq (%rsp), %rbp
movzbl 0xa(%rbp), %ebx
movl %ebx, %edi
callq 0x2632
testq %rax, %rax
je 0x2fe3
leaq 0x2d4a(%rip), %rdi      # 0x5d21
movq %rax, %rsi
xorl %eax, %eax
callq 0x1050
jmp 0x2ff3
leaq 0x2a47(%rip), %rdi      # 0x5a31
movl %ebx, %esi
xorl %eax, %eax
callq 0x1050
leaq 0x2a55(%rip), %rdi      # 0x5a4f
xorl %eax, %eax
callq 0x1050
movzbl 0x9(%rbp), %ebx
movl %ebx, %edi
callq 0x264b
testq %rax, %rax
je 0x3024
leaq 0x2d09(%rip), %rdi      # 0x5d21
movq %rax, %rsi
xorl %eax, %eax
callq 0x1050
jmp 0x3034
leaq 0x2a06(%rip), %rdi      # 0x5a31
movl %ebx, %esi
xorl %eax, %eax
callq 0x1050
movzbl %r14b, %ebx
leaq 0x2a1d(%rip), %rdi      # 0x5a5c
xorl %eax, %eax
callq 0x1050
movl %ebx, %edi
callq 0x2664
testq %rax, %rax
movl %ebx, 0x14(%rsp)
je 0x3069
leaq 0x2cc4(%rip), %rdi      # 0x5d21
movq %rax, %rsi
xorl %eax, %eax
callq 0x1050
jmp 0x3079
leaq 0x29c1(%rip), %rdi      # 0x5a31
movl %ebx, %esi
xorl %eax, %eax
callq 0x1050
movl $0xa, %edi
callq 0x1030
movl 0xc(%rbp), %r8d
movl %r8d, %esi
movl $0xff, %r14d
andl %r14d, %esi
incl %esi
movl %r8d, %edx
shrl $0x8, %edx
andl %r14d, %edx
incl %edx
movl %r8d, %ecx
shrl $0x10, %ecx
andl %r14d, %ecx
incl %ecx
shrl $0x18, %r8d
incl %r8d
leaq 0x29ac(%rip), %rdi      # 0x5a65
xorl %eax, %eax
callq 0x1050
movl 0x10(%rbp), %r8d
movl 0x14(%rbp), %r10d
movl %r8d, %esi
andl %r14d, %esi
movl %r8d, %edx
shrl $0x8, %edx
andl %r14d, %edx
movl %r8d, %ecx
shrl $0x10, %ecx
andl %r14d, %ecx
shrl $0x18, %r8d
movl %r10d, %r9d
andl %r14d, %r9d
movl %r10d, %r11d
shrl $0x8, %r11d
andl %r14d, %r11d
movl %r10d, %ebx
shrl $0x10, %ebx
andl %r14d, %ebx
shrl $0x18, %r10d
subq $0x8, %rsp
leaq 0x2975(%rip), %rdi      # 0x5a81
xorl %eax, %eax
pushq %r10
pushq %rbx
pushq %r11
callq 0x1050
addq $0x20, %rsp
movq 0x18(%rsp), %rax
leal -0x18(%rax), %ecx
cmpl $0x10, %ecx
jb 0x32f4
shrl $0x4, %ecx
cmpl $0x10, %ecx
movl $0x10, %eax
cmovael %eax, %ecx
movl 0xc(%rsp), %eax
movq %rax, 0x28(%rsp)
cmpl $0x1, %ecx
adcl $0x0, %ecx
movq %rcx, 0x20(%rsp)
xorl %esi, %esi
leaq 0x1(%rsi), %r14
movq %r14, %rax
shlq $0x4, %rax
addq $0x18, %rax
cmpq 0x28(%rsp), %rax
ja 0x32f4
leaq (,%rsi,4), %rax
movq %rax, 0x30(%rsp)
movq %rsi, %r12
shlq $0x4, %r12
movzbl 0x1b(%r12,%rbp), %r15d
xorl %ebx, %ebx
leaq 0x2920(%rip), %rdi      # 0x5aae
xorl %eax, %eax
callq 0x1050
movzbl 0x1b(%r12,%rbp), %ebp
andl $-0x10, %ebp
leaq 0x2915(%rip), %rdi      # 0x5aba
movl %ebp, %esi
xorl %eax, %eax
callq 0x1050
movb $0x1, %r12b
movl $0x1, %edx
movl %ebx, %ecx
shll %cl, %edx
testb $0x1, %r12b
movq %r13, %rsi
leaq 0x2926(%rip), %rax      # 0x5aee
cmovneq %rax, %rsi
btl %ebx, %ebp
jae 0x321a
leal -0x10(%rdx), %eax
roll $0x1c, %eax
cmpl $0x7, %eax
ja 0x3209
movl $0x8b, %ecx
btl %eax, %ecx
jae 0x3209
movl %eax, %eax
leaq 0x1601(%rip), %rcx      # 0x47f0
movslq (%rcx,%rax,4), %rdx
addq %rcx, %rdx
xorl %r12d, %r12d
leaq 0x2c09(%rip), %rdi      # 0x5e09
xorl %eax, %eax
callq 0x1050
jmp 0x321a
xorl %r12d, %r12d
leaq 0x29de(%rip), %rdi      # 0x5bf1
xorl %eax, %eax
callq 0x1050
incl %ebx
cmpl $0x20, %ebx
jne 0x31b1
andl $0xf, %r15d
leaq 0x11be(%rip), %rdi      # 0x43ea
callq 0x1040
leaq 0x2899(%rip), %rdi      # 0x5ad1
movl %r15d, %esi
xorl %eax, %eax
callq 0x1050
movl 0x14(%rsp), %edi
movl %r15d, %esi
callq 0x27ce
testq %rax, %rax
je 0x3266
leaq 0x288e(%rip), %rdi      # 0x5ae8
movq %rax, %rsi
xorl %eax, %eax
callq 0x1050
jmp 0x3277
leaq 0x2882(%rip), %rdi      # 0x5aef
movl %r15d, %esi
xorl %eax, %eax
callq 0x1050
movq (%rsp), %rbp
movq 0x30(%rsp), %r15
movl 0x18(%rbp,%r15,4), %esi
movzwl %si, %edx
shrl $0x10, %esi
movl $0xff, %ebx
andl %ebx, %esi
incl %esi
leaq 0x285b(%rip), %rdi      # 0x5af6
xorl %eax, %eax
callq 0x1050
movl 0x1c(%rbp,%r15,4), %r8d
movl %r8d, %esi
andl %ebx, %esi
movl %r8d, %edx
shrl $0x8, %edx
andl %ebx, %edx
movl %r8d, %ecx
shrl $0x10, %ecx
andl %ebx, %ecx
shrl $0x18, %r8d
leaq 0x284f(%rip), %rdi      # 0x5b16
xorl %eax, %eax
callq 0x1050
movl 0x20(%rbp,%r15,4), %esi
movl 0x24(%rbp,%r15,4), %edx
leaq 0x2855(%rip), %rdi      # 0x5b34
xorl %eax, %eax
callq 0x1050
movq %r14, %rsi
cmpq 0x20(%rsp), %r14
jne 0x3151
movq 0x18(%rsp), %rcx
cmpl $0x9, %ecx
movl $0x8, %eax
cmovbl %eax, %ecx
movl 0xc(%rsp), %r14d
subl %ecx, %r14d
movl 0x10(%rsp), %ebx
jb 0x2dad
cmpl $0x8, %ebx
ja 0x2dad
andl $-0x4, %ecx
addq %rcx, %rbp
incl %ebx
cmpl $0x7, %r14d
ja 0x2dc9
jmp 0x2dad