// File: /workspace/github_c_makefile_star2_O2/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 $0x28, %rsp
movl %esi, %r15d
movq %rdi, %r14
xorl %esi, %esi
cmpl $0x4, %r15d
jb 0x2b37
movl (%r14), %esi
cmpl %r15d, %esi
cmovbl %esi, %r15d
cmpl $0x4, %r15d
jae 0x2b53
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
addq $0x4, %r14
addl $-0x4, %r15d
leaq 0x2e48(%rip), %rdi      # 0x59aa
xorl %eax, %eax
callq 0x1050
xorl %r13d, %r13d
cmpl $0x9, %r13d
ja 0x2b44
cmpl $0x8, %r15d
jb 0x2b44
movl (%r14), %ebx
movl 0x4(%r14), %r12d
leaq 0x2e39(%rip), %rdi      # 0x59bf
xorl %eax, %eax
callq 0x1050
movl %ebx, %ebp
andl $0x1ffff, %ebp          # imm = 0x1FFFF
movl %r13d, 0xc(%rsp)
je 0x2bae
leaq 0x2e5e(%rip), %rdi      # 0x5a01
movl %ebp, %esi
xorl %eax, %eax
callq 0x1050
jmp 0x2bc3
leaq 0x313c(%rip), %rdi      # 0x5cf1
leaq 0x1c24(%rip), %rsi      # 0x47e0
xorl %eax, %eax
callq 0x1050
movl %ebx, %r13d
shrl $0x11, %r13d
leaq 0x2dfa(%rip), %rdi      # 0x59cb
xorl %eax, %eax
callq 0x1050
leaq 0x1c19(%rip), %rsi      # 0x47f8
testl %r13d, %r13d
je 0x2c06
cmpl $0x6002, %r13d          # imm = 0x6002
je 0x2bff
cmpl $0x6001, %r13d          # imm = 0x6001
jne 0x2c16
leaq 0x1c21(%rip), %rsi      # 0x481e
jmp 0x2c06
leaq 0x1c44(%rip), %rsi      # 0x484a
leaq 0x30e4(%rip), %rdi      # 0x5cf1
xorl %eax, %eax
callq 0x1050
jmp 0x2c27
leaq 0x2de4(%rip), %rdi      # 0x5a01
movl %r13d, %esi
xorl %eax, %eax
callq 0x1050
leaq 0x2db0(%rip), %rdi      # 0x59de
xorl %eax, %eax
callq 0x1050
cmpw $0x2, %r12w
ja 0x2c5d
movl %r12d, %eax
andl $0x3, %eax
leaq 0x5197(%rip), %rcx      # 0x7de0
movq (%rcx,%rax,8), %rsi
leaq 0x309d(%rip), %rdi      # 0x5cf1
xorl %eax, %eax
callq 0x1050
jmp 0x2c6f
movzwl %r12w, %esi
leaq 0x2d99(%rip), %rdi      # 0x5a01
xorl %eax, %eax
callq 0x1050
shrl $0x10, %r12d
leaq 0x2d6f(%rip), %rdi      # 0x59e9
movq %r12, 0x18(%rsp)
movl %r12d, %esi
xorl %eax, %eax
callq 0x1050
pushq $0xa
popq %rdi
callq 0x1030
testl %ebx, %ebx
movl %r15d, 0x10(%rsp)
je 0x2cec
testl %ebp, %ebp
sete %al
addl $0xffff9fff, %r13d      # imm = 0xFFFF9FFF
cmpl $0x2, %r13d
setb %cl
testb %cl, %al
jne 0x2cbd
leaq 0x313e(%rip), %rdi      # 0x5df6
callq 0x1040
movq 0x18(%rsp), %rcx
cmpl $0x9, %ecx
pushq $0x8
popq %rax
cmovbl %eax, %ecx
movl 0x10(%rsp), %r15d
subl %ecx, %r15d
movl 0xc(%rsp), %r13d
jb 0x2b44
andl $-0x4, %ecx
addq %rcx, %r14
incl %r13d
jmp 0x2b6c
cmpl $0x18, %r15d
movq 0x18(%rsp), %r12
jb 0x2b44
movl 0x8(%r14), %ebx
movl %ebx, %ebp
shrl $0x18, %ebp
leaq 0x2cf9(%rip), %rdi      # 0x5a04
movl %ebp, %esi
xorl %eax, %eax
callq 0x1050
movl %ebp, %edi
leaq -0x900(%rip), %rsi      # 0x241d
callq 0x2fbd
leaq 0x2ce9(%rip), %rdi      # 0x5a12
xorl %eax, %eax
callq 0x1050
movzbl 0xa(%r14), %ebp
movl %ebp, %edi
callq 0x243a
testq %rax, %rax
je 0x2d54
leaq 0x2fa9(%rip), %rdi      # 0x5cf1
movq %rax, %rsi
xorl %eax, %eax
callq 0x1050
jmp 0x2d64
leaq 0x2ca6(%rip), %rdi      # 0x5a01
movl %ebp, %esi
xorl %eax, %eax
callq 0x1050
leaq 0x2cb4(%rip), %rdi      # 0x5a1f
xorl %eax, %eax
callq 0x1050
movzbl 0x9(%r14), %ebp
movl %ebp, %edi
callq 0x2453
testq %rax, %rax
je 0x2d96
leaq 0x2f67(%rip), %rdi      # 0x5cf1
movq %rax, %rsi
xorl %eax, %eax
callq 0x1050
jmp 0x2da6
leaq 0x2c64(%rip), %rdi      # 0x5a01
movl %ebp, %esi
xorl %eax, %eax
callq 0x1050
movzbl %bl, %ebx
leaq 0x2c7c(%rip), %rdi      # 0x5a2c
xorl %eax, %eax
callq 0x1050
movl %ebx, %edi
callq 0x246c
testq %rax, %rax
movl %ebx, 0x14(%rsp)
je 0x2dda
leaq 0x2f23(%rip), %rdi      # 0x5cf1
movq %rax, %rsi
xorl %eax, %eax
callq 0x1050
jmp 0x2dea
leaq 0x2c20(%rip), %rdi      # 0x5a01
movl %ebx, %esi
xorl %eax, %eax
callq 0x1050
pushq $0xa
popq %rdi
callq 0x1030
movl 0xc(%r14), %r8d
movl %r8d, %esi
movl $0xff, %ebp
andl %ebp, %esi
incl %esi
movl %r8d, %edx
shrl $0x8, %edx
andl %ebp, %edx
incl %edx
movl %r8d, %ecx
shrl $0x10, %ecx
andl %ebp, %ecx
incl %ecx
shrl $0x18, %r8d
incl %r8d
leaq 0x2c11(%rip), %rdi      # 0x5a35
xorl %eax, %eax
callq 0x1050
movl 0x10(%r14), %r8d
movl 0x14(%r14), %r10d
movl %r8d, %esi
andl %ebp, %esi
movl %r8d, %edx
shrl $0x8, %edx
andl %ebp, %edx
movl %r8d, %ecx
shrl $0x10, %ecx
andl %ebp, %ecx
shrl $0x18, %r8d
movl %r10d, %r9d
andl %ebp, %r9d
movl %r10d, %r11d
shrl $0x8, %r11d
andl %ebp, %r11d
movl %r10d, %ebx
shrl $0x10, %ebx
andl %ebp, %ebx
shrl $0x18, %r10d
subq $0x8, %rsp
leaq 0x2bde(%rip), %rdi      # 0x5a51
xorl %eax, %eax
pushq %r10
pushq %rbx
pushq %r11
callq 0x1050
addq $0x20, %rsp
leal -0x18(%r12), %ebp
shrl $0x4, %ebp
cmpl $0x10, %ebp
pushq $0x10
popq %rax
cmovael %eax, %ebp
movl %r15d, %eax
movq %rax, 0x20(%rsp)
pushq $0x28
popq %r15
xorl %r13d, %r13d
cmpq %r13, %rbp
je 0x2cbd
cmpq 0x20(%rsp), %r15
ja 0x2cbd
movzbl -0xd(%r14,%r15), %r12d
andl $0xf, %r12d
leaq 0x2bb6(%rip), %rdi      # 0x5a7e
movl %r13d, %esi
xorl %eax, %eax
callq 0x1050
movzbl -0xd(%r14,%r15), %ebx
andl $-0x10, %ebx
leaq 0x2ba8(%rip), %rdi      # 0x5a8a
movl %ebx, %esi
xorl %eax, %eax
callq 0x1050
movl %ebx, %edi
leaq -0x947(%rip), %rsi      # 0x25ad
callq 0x2fbd
leaq 0x14da(%rip), %rdi      # 0x43da
callq 0x1040
leaq 0x2b95(%rip), %rdi      # 0x5aa1
movl %r12d, %esi
xorl %eax, %eax
callq 0x1050
movl 0x14(%rsp), %edi
movl %r12d, %esi
callq 0x25d4
testq %rax, %rax
je 0x2f3a
leaq 0x2b8a(%rip), %rdi      # 0x5ab8
movq %rax, %rsi
xorl %eax, %eax
callq 0x1050
jmp 0x2f4b
leaq 0x2b7e(%rip), %rdi      # 0x5abf
movl %r12d, %esi
xorl %eax, %eax
callq 0x1050
movl -0x10(%r14,%r15), %esi
movzwl %si, %edx
shrl $0x10, %esi
movl $0xff, %ebx
andl %ebx, %esi
incl %esi
leaq 0x2b60(%rip), %rdi      # 0x5ac6
xorl %eax, %eax
callq 0x1050
movl -0xc(%r14,%r15), %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 0x2b54(%rip), %rdi      # 0x5ae6
xorl %eax, %eax
callq 0x1050
movl -0x8(%r14,%r15), %esi
movl -0x4(%r14,%r15), %edx
leaq 0x2b5a(%rip), %rdi      # 0x5b04
xorl %eax, %eax
callq 0x1050
addq $0x10, %r15
incq %r13
jmp 0x2ea3