// File: rpavlik[P]edid-decode/parse-cta-block.cpp
// Function: edid_state::parse_cta_block(unsigned char const*)
void edid_state::parse_cta_block(const unsigned char *x)
{
	unsigned version = x[1];
	unsigned offset = x[2];
	const unsigned char *detailed;

	// See Table 52 of CTA-861-G for a description of Byte 3

	printf("  Revision: %u\n", version);
	if (version == 0)
		fail("Invalid CTA-861 Extension revision 0.\n");
	if (version == 2)
		fail("Deprecated CTA-861 Extension revision 2.\n");
	if (cta.has_hdmi && version != 3)
		fail("The HDMI Specification requires CTA Extension revision 3.\n");
	if (version > 3)
		warn("Unknown CTA-861 Extension revision %u.\n", version);

	if (version >= 1) do {
		if (version == 1 && x[3] != 0)
			fail("Non-zero byte 3.\n");

		if (offset < 4)
			break;

		if (version < 3 && ((offset - 4) / 8)) {
			printf("  8-byte timing descriptors: %u\n", (offset - 4) / 8);
			fail("8-byte descriptors were never used.\n");
		}

		if (version >= 2) {
			if (x[3] & 0x80)
				printf("  Underscans IT Video Formats by default\n");
			else
				warn("IT Video Formats are overscanned by default, but normally this should be underscanned.\n");
			if (x[3] & 0x40)
				printf("  Basic audio support\n");
			if (x[3] & 0x20)
				printf("  Supports YCbCr 4:4:4\n");
			if (x[3] & 0x10)
				printf("  Supports YCbCr 4:2:2\n");
			// Disable this test: this fails a lot of EDIDs, and there are
			// also some corner cases where you only want to receive 4:4:4
			// and refuse a fallback to 4:2:2.
//			if ((x[3] & 0x30) && (x[3] & 0x30) != 0x30)
//				msg(!cta.has_hdmi, "If YCbCr support is indicated, then both 4:2:2 and 4:4:4 %s be supported.\n",
//				    cta.has_hdmi ? "shall" : "should");
			printf("  Native detailed modes: %u\n", x[3] & 0x0f);
			if (cta.first_block)
				cta.byte3 = x[3];
			else if (x[3] != cta.byte3)
				fail("Byte 3 must be the same for all CTA-861 Extension Blocks.\n");
			if (cta.first_block) {
				unsigned native_dtds = x[3] & 0x0f;

				cta.native_timings.clear();
				if (!native_dtds && !cta.has_vfpdb) {
					cta.first_svd_might_be_preferred = true;
				} else if (native_dtds > cta.preparsed_total_dtds) {
					fail("There are more Native DTDs (%u) than DTDs (%u).\n",
					     native_dtds, cta.preparsed_total_dtds);
				}
				if (native_dtds > cta.preparsed_total_dtds)
					native_dtds = cta.preparsed_total_dtds;
				for (unsigned i = 0; i < native_dtds; i++) {
					char type[16];

					sprintf(type, "DTD %3u", i + 1);
					cta.native_timings.push_back(timings_ext(i + 129, type));
				}
				if (cta.has_hdmi && block_nr != (block_map.saw_block_1 ? 2 : 1))
					fail("The HDMI Specification requires that the first Extension Block (that is not a Block Map) is an CTA-861 Extension Block.\n");
			}
		}
		if (version >= 3) {
			unsigned i;

			for (i = 4; i < offset; i += (x[i] & 0x1f) + 1) {
				unsigned tag = (x[i] & 0xe0) << 3;

				if (tag == 0x700)
					tag |= x[i + 1];
				bool duplicate = cta.found_tags.find(tag) != cta.found_tags.end();

				cta_block(x + i, duplicate);
				if (!duplicate)
					cta.found_tags.insert(tag);
			}

			data_block.clear();
			if (i != offset)
				fail("Offset is %u, but should be %u.\n", offset, i);
		}

		data_block = "Detailed Timing Descriptors";
		base.seen_non_detailed_descriptor = false;
		bool first = true;
		for (detailed = x + offset; detailed + 17 < x + 127; detailed += 18) {
			if (memchk(detailed, 18))
				break;
			if (first) {
				first = false;
				printf("  %s:\n", data_block.c_str());
			}
			detailed_block(detailed);
		}
		if (!memchk(detailed, x + 127 - detailed)) {
			data_block = "Padding";
			fail("CTA-861 padding contains non-zero bytes.\n");
		}
	} while (0);

	data_block.clear();
	if (base.has_serial_number && base.has_serial_string)
		warn("Display Product Serial Number is set, so the Serial Number in the Base EDID should be 0.\n");
	if (!cta.has_vic_1 && !base.has_640x480p60_est_timing)
		fail("Required 640x480p60 timings are missing in the established timings"
		     " and the SVD list (VIC 1).\n");
	if ((cta.supported_hdmi_vic_vsb_codes & cta.supported_hdmi_vic_codes) !=
	    cta.supported_hdmi_vic_codes)
		fail("HDMI VIC Codes must have their CTA-861 VIC equivalents in the VSB.\n");
	if (!cta.has_vcdb)
		fail("Missing VCDB, needed for Set Selectable RGB Quantization to avoid interop issues.\n");
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x170, %rsp            # imm = 0x170
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x148(%rbp)
movq -0x10(%rbp), %rax
movzbl 0x1(%rax), %eax
movl %eax, -0x14(%rbp)
movq -0x10(%rbp), %rax
movzbl 0x2(%rax), %eax
movl %eax, -0x18(%rbp)
movl -0x14(%rbp), %esi
leaq 0x1d169(%rip), %rdi     # 0x3aca7
movb $0x0, %al
callq 0x4050
cmpl $0x0, -0x14(%rbp)
jne 0x1db5b
xorl %edi, %edi
leaq 0x1d163(%rip), %rsi     # 0x3acb7
movb $0x0, %al
callq 0x47d0
cmpl $0x2, -0x14(%rbp)
jne 0x1db71
xorl %edi, %edi
leaq 0x1d174(%rip), %rsi     # 0x3acde
movb $0x0, %al
callq 0x47d0
movq -0x148(%rbp), %rax
testb $0x1, 0x2c3(%rax)
je 0x1db97
cmpl $0x3, -0x14(%rbp)
je 0x1db97
xorl %edi, %edi
leaq 0x1d178(%rip), %rsi     # 0x3ad08
movb $0x0, %al
callq 0x47d0
cmpl $0x3, -0x14(%rbp)
jbe 0x1dbb3
movl -0x14(%rbp), %edx
movl $0x1, %edi
leaq 0x1d197(%rip), %rsi     # 0x3ad43
movb $0x0, %al
callq 0x47d0
cmpl $0x1, -0x14(%rbp)
jb 0x1e1f3
jmp 0x1dbbf
cmpl $0x1, -0x14(%rbp)
jne 0x1dbe2
movq -0x10(%rbp), %rax
movzbl 0x3(%rax), %eax
cmpl $0x0, %eax
je 0x1dbe2
xorl %edi, %edi
leaq 0x1d190(%rip), %rsi     # 0x3ad6b
movb $0x0, %al
callq 0x47d0
cmpl $0x4, -0x18(%rbp)
jae 0x1dbed
jmp 0x1e1f1
cmpl $0x3, -0x14(%rbp)
jae 0x1dc28
movl -0x18(%rbp), %eax
subl $0x4, %eax
shrl $0x3, %eax
cmpl $0x0, %eax
je 0x1dc28
movl -0x18(%rbp), %esi
subl $0x4, %esi
shrl $0x3, %esi
leaq 0x1d16c(%rip), %rdi     # 0x3ad7d
movb $0x0, %al
callq 0x4050
xorl %edi, %edi
leaq 0x1d17d(%rip), %rsi     # 0x3ad9e
movb $0x0, %al
callq 0x47d0
cmpl $0x2, -0x14(%rbp)
jb 0x1df75
movq -0x10(%rbp), %rax
movzbl 0x3(%rax), %eax
andl $0x80, %eax
cmpl $0x0, %eax
je 0x1dc54
leaq 0x1d178(%rip), %rdi     # 0x3adc3
movb $0x0, %al
callq 0x4050
jmp 0x1dc67
movl $0x1, %edi
leaq 0x1d18d(%rip), %rsi     # 0x3aded
movb $0x0, %al
callq 0x47d0
movq -0x10(%rbp), %rax
movzbl 0x3(%rax), %eax
andl $0x40, %eax
cmpl $0x0, %eax
je 0x1dc85
leaq 0x1d1c7(%rip), %rdi     # 0x3ae45
movb $0x0, %al
callq 0x4050
movq -0x10(%rbp), %rax
movzbl 0x3(%rax), %eax
andl $0x20, %eax
cmpl $0x0, %eax
je 0x1dca3
leaq 0x1d1c0(%rip), %rdi     # 0x3ae5c
movb $0x0, %al
callq 0x4050
movq -0x10(%rbp), %rax
movzbl 0x3(%rax), %eax
andl $0x10, %eax
cmpl $0x0, %eax
je 0x1dcc1
leaq 0x1d1ba(%rip), %rdi     # 0x3ae74
movb $0x0, %al
callq 0x4050
movq -0x10(%rbp), %rax
movzbl 0x3(%rax), %esi
andl $0xf, %esi
leaq 0x1d1b9(%rip), %rdi     # 0x3ae8c
movb $0x0, %al
callq 0x4050
movq -0x148(%rbp), %rax
testb $0x1, 0x2d5(%rax)
je 0x1dd00
movq -0x148(%rbp), %rax
movq -0x10(%rbp), %rcx
movb 0x3(%rcx), %cl
movb %cl, 0x2c2(%rax)
jmp 0x1dd2c
movq -0x148(%rbp), %rcx
movq -0x10(%rbp), %rax
movzbl 0x3(%rax), %eax
movzbl 0x2c2(%rcx), %ecx
cmpl %ecx, %eax
je 0x1dd2a
xorl %edi, %edi
leaq 0x1d186(%rip), %rsi     # 0x3aea9
movb $0x0, %al
callq 0x47d0
jmp 0x1dd2c
movq -0x148(%rbp), %rax
testb $0x1, 0x2d5(%rax)
je 0x1df73
movq -0x148(%rbp), %rdi
movq -0x10(%rbp), %rax
movzbl 0x3(%rax), %eax
andl $0xf, %eax
movl %eax, -0x24(%rbp)
addq $0x180, %rdi            # imm = 0x180
addq $0x128, %rdi            # imm = 0x128
callq 0x14a90
cmpl $0x0, -0x24(%rbp)
jne 0x1dd8e
movq -0x148(%rbp), %rax
testb $0x1, 0x2c5(%rax)
jne 0x1dd8e
movq -0x148(%rbp), %rax
movb $0x1, 0x2c1(%rax)
jmp 0x1ddc2
movq -0x148(%rbp), %rcx
movl -0x24(%rbp), %eax
cmpl 0x180(%rcx), %eax
jbe 0x1ddc0
movq -0x148(%rbp), %rax
movl -0x24(%rbp), %edx
movl 0x180(%rax), %ecx
xorl %edi, %edi
leaq 0x1d12b(%rip), %rsi     # 0x3aee4
movb $0x0, %al
callq 0x47d0
jmp 0x1ddc2
movq -0x148(%rbp), %rcx
movl -0x24(%rbp), %eax
cmpl 0x180(%rcx), %eax
jbe 0x1dde4
movq -0x148(%rbp), %rax
movl 0x180(%rax), %eax
movl %eax, -0x24(%rbp)
movl $0x0, -0x28(%rbp)
movl -0x28(%rbp), %eax
cmpl -0x24(%rbp), %eax
jae 0x1df2b
movl -0x28(%rbp), %edx
incl %edx
leaq 0x1b7df(%rip), %rsi     # 0x395e2
xorl %eax, %eax
leaq -0x40(%rbp), %rdi
movq %rdi, -0x158(%rbp)
callq 0x40a0
movq -0x148(%rbp), %rax
addq $0x2a8, %rax            # imm = 0x2A8
movq %rax, -0x168(%rbp)
movl -0x28(%rbp), %eax
addl $0x81, %eax
movl %eax, -0x15c(%rbp)
leaq -0xf9(%rbp), %rdi
movq %rdi, -0x150(%rbp)
callq 0x4560
movq -0x158(%rbp), %rsi
movq -0x150(%rbp), %rdx
leaq -0xf8(%rbp), %rdi
callq 0xb510
jmp 0x1de66
movl -0x15c(%rbp), %esi
leaq -0xd8(%rbp), %rdi
leaq -0xf8(%rbp), %rdx
callq 0x20000
jmp 0x1de81
movq -0x168(%rbp), %rdi
leaq -0xd8(%rbp), %rsi
callq 0x1ff90
jmp 0x1de96
leaq -0xd8(%rbp), %rdi
callq 0xc3d0
leaq -0xf8(%rbp), %rdi
callq 0x41f0
leaq -0xf9(%rbp), %rdi
callq 0x4370
movl -0x28(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x28(%rbp)
jmp 0x1ddeb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x108(%rbp)
movl %eax, -0x10c(%rbp)
jmp 0x1df1a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x108(%rbp)
movl %eax, -0x10c(%rbp)
jmp 0x1df0e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x108(%rbp)
movl %eax, -0x10c(%rbp)
leaq -0xd8(%rbp), %rdi
callq 0xc3d0
leaq -0xf8(%rbp), %rdi
callq 0x41f0
leaq -0xf9(%rbp), %rdi
callq 0x4370
jmp 0x1e2ba
movq -0x148(%rbp), %rax
testb $0x1, 0x2c3(%rax)
je 0x1df71
movq -0x148(%rbp), %rcx
movl 0x8(%rcx), %eax
movb 0x978(%rcx), %sil
movl $0x1, %ecx
movl $0x2, %edx
testb $0x1, %sil
cmovnel %edx, %ecx
cmpl %ecx, %eax
je 0x1df71
xorl %edi, %edi
leaq 0x1cfab(%rip), %rsi     # 0x3af15
movb $0x0, %al
callq 0x47d0
jmp 0x1df73
jmp 0x1df75
cmpl $0x3, -0x14(%rbp)
jb 0x1e0f2
movl $0x4, -0x110(%rbp)
movl -0x110(%rbp), %eax
cmpl -0x18(%rbp), %eax
jae 0x1e0bc
movq -0x10(%rbp), %rax
movl -0x110(%rbp), %ecx
movzbl (%rax,%rcx), %eax
andl $0xe0, %eax
shll $0x3, %eax
movl %eax, -0x114(%rbp)
cmpl $0x700, -0x114(%rbp)    # imm = 0x700
jne 0x1dfdf
movq -0x10(%rbp), %rax
movl -0x110(%rbp), %ecx
addl $0x1, %ecx
movl %ecx, %ecx
movzbl (%rax,%rcx), %eax
orl -0x114(%rbp), %eax
movl %eax, -0x114(%rbp)
movq -0x148(%rbp), %rdi
addq $0x180, %rdi            # imm = 0x180
addq $0x60, %rdi
leaq -0x114(%rbp), %rsi
callq 0x20260
movq -0x148(%rbp), %rdi
movq %rax, -0x120(%rbp)
addq $0x180, %rdi            # imm = 0x180
addq $0x60, %rdi
callq 0x202a0
movq %rax, -0x128(%rbp)
leaq -0x120(%rbp), %rdi
leaq -0x128(%rbp), %rsi
callq 0x20230
movq -0x148(%rbp), %rdi
andb $0x1, %al
movb %al, -0x115(%rbp)
movq -0x10(%rbp), %rsi
movl -0x110(%rbp), %eax
addq %rax, %rsi
movb -0x115(%rbp), %al
andb $0x1, %al
movzbl %al, %edx
callq 0x1c230
testb $0x1, -0x115(%rbp)
jne 0x1e095
movq -0x148(%rbp), %rdi
addq $0x180, %rdi            # imm = 0x180
addq $0x60, %rdi
leaq -0x114(%rbp), %rsi
callq 0x202d0
movq %rax, -0x138(%rbp)
movb %dl, -0x130(%rbp)
jmp 0x1e097
movq -0x10(%rbp), %rax
movl -0x110(%rbp), %ecx
movzbl (%rax,%rcx), %eax
andl $0x1f, %eax
addl $0x1, %eax
addl -0x110(%rbp), %eax
movl %eax, -0x110(%rbp)
jmp 0x1df89
movq -0x148(%rbp), %rdi
addq $0x30, %rdi
callq 0x4400
movl -0x110(%rbp), %eax
cmpl -0x18(%rbp), %eax
je 0x1e0f0
movl -0x18(%rbp), %edx
movl -0x110(%rbp), %ecx
xorl %edi, %edi
leaq 0x1cea5(%rip), %rsi     # 0x3af8e
movb $0x0, %al
callq 0x47d0
jmp 0x1e0f2
movq -0x148(%rbp), %rdi
addq $0x30, %rdi
leaq 0x174d7(%rip), %rsi     # 0x355db
callq 0x4420
movq -0x148(%rbp), %rax
movb $0x0, 0xc4(%rax)
movb $0x1, -0x139(%rbp)
movq -0x10(%rbp), %rax
movl -0x18(%rbp), %ecx
addq %rcx, %rax
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
addq $0x11, %rax
movq -0x10(%rbp), %rcx
addq $0x7f, %rcx
cmpq %rcx, %rax
jae 0x1e1a8
movq -0x20(%rbp), %rdi
movl $0x12, %esi
xorl %edx, %edx
callq 0x7810
testb $0x1, %al
jne 0x1e157
jmp 0x1e159
jmp 0x1e1a8
testb $0x1, -0x139(%rbp)
je 0x1e18a
movq -0x148(%rbp), %rdi
movb $0x0, -0x139(%rbp)
addq $0x30, %rdi
callq 0x4150
movq %rax, %rsi
leaq 0x15f6e(%rip), %rdi     # 0x340f1
movb $0x0, %al
callq 0x4050
movq -0x148(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x12020
movq -0x20(%rbp), %rax
addq $0x12, %rax
movq %rax, -0x20(%rbp)
jmp 0x1e12c
movq -0x20(%rbp), %rdi
movq -0x10(%rbp), %rax
addq $0x7f, %rax
movq -0x20(%rbp), %rcx
subq %rcx, %rax
movl %eax, %esi
xorl %edx, %edx
callq 0x7810
testb $0x1, %al
jne 0x1e1ef
movq -0x148(%rbp), %rdi
addq $0x30, %rdi
leaq 0x1cdd5(%rip), %rsi     # 0x3afaf
callq 0x4420
xorl %edi, %edi
leaq 0x1cdcf(%rip), %rsi     # 0x3afb7
movb $0x0, %al
callq 0x47d0
jmp 0x1e1f1
jmp 0x1e1f3
movq -0x148(%rbp), %rdi
addq $0x30, %rdi
callq 0x4400
movq -0x148(%rbp), %rax
testb $0x1, 0x8e(%rax)
je 0x1e236
movq -0x148(%rbp), %rax
testb $0x1, 0x8f(%rax)
je 0x1e236
movl $0x1, %edi
leaq 0x1cdb2(%rip), %rsi     # 0x3afe1
movb $0x0, %al
callq 0x47d0
movq -0x148(%rbp), %rax
testb $0x1, 0x2c0(%rax)
jne 0x1e266
movq -0x148(%rbp), %rax
testb $0x1, 0xc5(%rax)
jne 0x1e266
xorl %edi, %edi
leaq 0x1cddc(%rip), %rsi     # 0x3b03b
movb $0x0, %al
callq 0x47d0
movq -0x148(%rbp), %rcx
movl 0x2dc(%rcx), %eax
andl 0x2d8(%rcx), %eax
cmpl 0x2d8(%rcx), %eax
je 0x1e291
xorl %edi, %edi
leaq 0x1ce0f(%rip), %rsi     # 0x3b099
movb $0x0, %al
callq 0x47d0
movq -0x148(%rbp), %rax
testb $0x1, 0x2c4(%rax)
jne 0x1e2b1
xorl %edi, %edi
leaq 0x1ce33(%rip), %rsi     # 0x3b0dd
movb $0x0, %al
callq 0x47d0
addq $0x170, %rsp            # imm = 0x170
popq %rbp
retq
movq -0x108(%rbp), %rdi
callq 0x4550
nopw %cs:(%rax,%rax)