// File: rpavlik[P]edid-decode/parse-cta-block.cpp
// Function: cta_amd(unsigned char const*, unsigned int)
static void cta_amd(const unsigned char *x, unsigned length)
{
	// These Freesync values are reversed engineered by looking
	// at existing EDIDs.
	printf("    Version: %u.%u\n", x[0], x[1]);
	printf("    Minimum Refresh Rate: %u Hz\n", x[2]);
	printf("    Maximum Refresh Rate: %u Hz\n", x[3]);
	// Freesync 1.x flags
	// One or more of the 0xe6 bits signal that the VESA MCCS
	// protocol is used to switch the Freesync range
	printf("    Flags 1.x: 0x%02x%s\n", x[4],
	       (x[4] & 0xe6) ? " (MCCS)" : "");
	if (length >= 10) {
		// Freesync 2.x flags
		// Bit 2 no doubt indicates if the monitor supports Local Dimming
		// There are probably also bits to signal support of the
		// FreeSync2_scRGB and FreeSync2_Gamma22 HDR display modes.
		// I suspect bits 0 and 1.
		printf("    Flags 2.x: 0x%02x\n", x[5]);
		// The AMD tone mapping tutorial referred to in the URL below
		// mentions that the Freesync HDR info reports max/min
		// luminance of the monitor with and without local dimming.
		//
		// https://gpuopen.com/learn/using-amd-freesync-premium-pro-hdr-code-samples/
		//
		// So I assume that the first two luminance values are
		// the max/min luminance of the display and the next two
		// luminance values are the max/min luminance values when
		// local dimming is disabled. The values I get seem to
		// support that.
		printf("    Maximum luminance: %u (%.3f cd/m^2)\n",
		       x[6], 50.0 * pow(2, x[6] / 32.0));
		printf("    Minimum luminance: %u (%.3f cd/m^2)\n",
		       x[7], (50.0 * pow(2, x[6] / 32.0)) * pow(x[7] / 255.0, 2) / 100.0);
		if (x[5] & 4) {
			// One or both bytes can be 0. The meaning of that
			// is unknown.
			printf("    Maximum luminance (without local dimming): %u (%.3f cd/m^2)\n",
			       x[8], 50.0 * pow(2, x[8] / 32.0));
			printf("    Minimum luminance (without local dimming): %u (%.3f cd/m^2)\n",
			       x[9], (50.0 * pow(2, x[8] / 32.0)) * pow(x[9] / 255.0, 2) / 100.0);
		} else {
			// These bytes are always 0x08 0x2f. If these values
			// represent max/min luminance as well, then these
			// would map to 59.460 and 0.020 cd/m^2 respectively.
			// I wonder if this somehow relates to SDR.
			printf("    Unknown: 0x%02x 0x%02x\n", x[8], x[9]);
		}
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq -0x8(%rbp), %rax
movzbl (%rax), %esi
movq -0x8(%rbp), %rax
movzbl 0x1(%rax), %edx
leaq 0x205e9(%rip), %rdi     # 0x3d7ae
movb $0x0, %al
callq 0x4050
movq -0x8(%rbp), %rax
movzbl 0x2(%rax), %esi
leaq 0x205e7(%rip), %rdi     # 0x3d7c2
movb $0x0, %al
callq 0x4050
movq -0x8(%rbp), %rax
movzbl 0x3(%rax), %esi
leaq 0x205f2(%rip), %rdi     # 0x3d7e3
movb $0x0, %al
callq 0x4050
movq -0x8(%rbp), %rax
movzbl 0x4(%rax), %esi
movq -0x8(%rbp), %rax
movzbl 0x4(%rax), %ecx
andl $0xe6, %ecx
leaq 0x12ca4(%rip), %rdx     # 0x2feb9
leaq 0x20601(%rip), %rax     # 0x3d81d
cmpl $0x0, %ecx
cmovneq %rax, %rdx
leaq 0x205da(%rip), %rdi     # 0x3d804
movb $0x0, %al
callq 0x4050
cmpl $0xa, -0xc(%rbp)
jb 0x1d439
movq -0x8(%rbp), %rax
movzbl 0x5(%rax), %esi
leaq 0x205db(%rip), %rdi     # 0x3d825
movb $0x0, %al
callq 0x4050
movq -0x8(%rbp), %rax
movzbl 0x6(%rax), %eax
movl %eax, -0x20(%rbp)
movq -0x8(%rbp), %rax
movzbl 0x6(%rax), %eax
cvtsi2sd %eax, %xmm0
movsd 0x1c148(%rip), %xmm1    # 0x393b8
divsd %xmm1, %xmm0
movl $0x2, %edi
callq 0x20390
movl -0x20(%rbp), %esi
movaps %xmm0, %xmm1
movsd 0x1c124(%rip), %xmm0    # 0x393b0
mulsd %xmm1, %xmm0
leaq 0x205a5(%rip), %rdi     # 0x3d83c
movb $0x1, %al
callq 0x4050
movq -0x8(%rbp), %rax
movzbl 0x7(%rax), %eax
movl %eax, -0x1c(%rbp)
movq -0x8(%rbp), %rax
movzbl 0x6(%rax), %eax
cvtsi2sd %eax, %xmm0
movsd 0x1c0fb(%rip), %xmm1    # 0x393b8
divsd %xmm1, %xmm0
movl $0x2, %edi
callq 0x20390
movaps %xmm0, %xmm1
movsd 0x1c0da(%rip), %xmm0    # 0x393b0
mulsd %xmm1, %xmm0
movsd %xmm0, -0x18(%rbp)
movq -0x8(%rbp), %rax
movzbl 0x7(%rax), %eax
cvtsi2sd %eax, %xmm0
movsd 0x1c0cd(%rip), %xmm1    # 0x393c0
divsd %xmm1, %xmm0
movl $0x2, %edi
callq 0x203c0
movl -0x1c(%rbp), %esi
movaps %xmm0, %xmm1
movsd -0x18(%rbp), %xmm0
mulsd %xmm1, %xmm0
movsd 0x11d20(%rip), %xmm1    # 0x2f038
divsd %xmm1, %xmm0
leaq 0x20542(%rip), %rdi     # 0x3d865
movb $0x1, %al
callq 0x4050
movq -0x8(%rbp), %rax
movzbl 0x5(%rax), %eax
andl $0x4, %eax
cmpl $0x0, %eax
je 0x1d419
movq -0x8(%rbp), %rax
movzbl 0x8(%rax), %eax
movl %eax, -0x30(%rbp)
movq -0x8(%rbp), %rax
movzbl 0x8(%rax), %eax
cvtsi2sd %eax, %xmm0
movsd 0x1c05b(%rip), %xmm1    # 0x393b8
divsd %xmm1, %xmm0
movl $0x2, %edi
callq 0x20390
movl -0x30(%rbp), %esi
movaps %xmm0, %xmm1
movsd 0x1c037(%rip), %xmm0    # 0x393b0
mulsd %xmm1, %xmm0
leaq 0x2050a(%rip), %rdi     # 0x3d88e
movb $0x1, %al
callq 0x4050
movq -0x8(%rbp), %rax
movzbl 0x9(%rax), %eax
movl %eax, -0x2c(%rbp)
movq -0x8(%rbp), %rax
movzbl 0x8(%rax), %eax
cvtsi2sd %eax, %xmm0
movsd 0x1c00e(%rip), %xmm1    # 0x393b8
divsd %xmm1, %xmm0
movl $0x2, %edi
callq 0x20390
movaps %xmm0, %xmm1
movsd 0x1bfed(%rip), %xmm0    # 0x393b0
mulsd %xmm1, %xmm0
movsd %xmm0, -0x28(%rbp)
movq -0x8(%rbp), %rax
movzbl 0x9(%rax), %eax
cvtsi2sd %eax, %xmm0
movsd 0x1bfe0(%rip), %xmm1    # 0x393c0
divsd %xmm1, %xmm0
movl $0x2, %edi
callq 0x203c0
movl -0x2c(%rbp), %esi
movaps %xmm0, %xmm1
movsd -0x28(%rbp), %xmm0
mulsd %xmm1, %xmm0
movsd 0x11c33(%rip), %xmm1    # 0x2f038
divsd %xmm1, %xmm0
leaq 0x204bf(%rip), %rdi     # 0x3d8cf
movb $0x1, %al
callq 0x4050
jmp 0x1d437
movq -0x8(%rbp), %rax
movzbl 0x8(%rax), %esi
movq -0x8(%rbp), %rax
movzbl 0x9(%rax), %edx
leaq 0x204e0(%rip), %rdi     # 0x3d910
movb $0x0, %al
callq 0x4050
jmp 0x1d439
addq $0x30, %rsp
popq %rbp
retq
nop