// File: /workspace/github_cpp_makefile_star2_O1/SYZYGYfpga[P]syzygy-tools/dna-tools/dna-writer.cpp
// Function: main
int main(int argc, char *argv[])
{
	std::vector<uint8_t> dna_header(SZG_DNA_HEADER_LENGTH_V1);
	uint8_t min_ver_major, min_ver_minor;

	// Print usage if there are not enough or too many arguments
	if ((argc < 3) || (argc > 4)) {
		std::cout << "USAGE: " << argv[0];
		std::cout << " in_file out_file [serial]\n";
		std::cout << "  If no serial is provided it will be ";
		std::cout << "extracted from the JSON input file\n";
		return 0;
	}

	std::ifstream input_file(argv[1]);
	std::ofstream output_file(argv[2], std::ios::out | std::ios::binary);

	json dna_json;

	// Parse the input data
	input_file >> dna_json;

	dna_header[SZG_DNA_PTR_HEADER_LENGTH] = SZG_DNA_HEADER_LENGTH_V1 & 0xFF;
	dna_header[SZG_DNA_PTR_HEADER_LENGTH + 1] =
	    (SZG_DNA_HEADER_LENGTH_V1 & 0xFF00) >> 8;

	dna_header[SZG_DNA_PTR_DNA_MAJOR] = DNA_SPEC_MAJOR;
	dna_header[SZG_DNA_PTR_DNA_MINOR] = DNA_SPEC_MINOR;

	// By default the DNA should be compatible with any version of the spec.
	min_ver_major = 0;
	min_ver_minor = 0;

	// TXR4 peripherals require version > 1.1
	if (dna_json["is_txr4"].get<bool>() == true) {
		if (min_ver_major < 1) {
			min_ver_major = 1;
			min_ver_minor = 1;
		} else if ((min_ver_major == 1) &&
		           (min_ver_minor < 1)) {
			min_ver_minor = 1;
		}
	}

	dna_header[SZG_DNA_PTR_DNA_REQUIRED_MAJOR] = min_ver_major;
	dna_header[SZG_DNA_PTR_DNA_REQUIRED_MINOR] = min_ver_minor;

	dna_header[SZG_DNA_PTR_MAX_5V_LOAD] = dna_json["max_5v_load"].get<uint16_t>() & 0xFF;
	dna_header[SZG_DNA_PTR_MAX_5V_LOAD + 1] = dna_json["max_5v_load"].get<uint16_t>() >> 8;
	dna_header[SZG_DNA_PTR_MAX_33V_LOAD] = dna_json["max_3v3_load"].get<uint16_t>() & 0xFF;
	dna_header[SZG_DNA_PTR_MAX_33V_LOAD + 1] = dna_json["max_3v3_load"].get<uint16_t>() >> 8;
	dna_header[SZG_DNA_PTR_MAX_VIO_LOAD] = dna_json["max_vio_load"].get<uint16_t>() & 0xFF;
	dna_header[SZG_DNA_PTR_MAX_VIO_LOAD + 1] = dna_json["max_vio_load"].get<uint16_t>() >> 8;

	dna_header[SZG_DNA_PTR_ATTRIBUTES] |= dna_json["is_lvds"].get<bool>() ?
	    SZG_ATTR_LVDS : 0;
	dna_header[SZG_DNA_PTR_ATTRIBUTES] |= dna_json["is_doublewide"].get<bool>() ?
	    SZG_ATTR_DOUBLEWIDE : 0;
	dna_header[SZG_DNA_PTR_ATTRIBUTES] |= dna_json["is_txr4"].get<bool>() ?
	    SZG_ATTR_TXR4 : 0;

	// Run through each range and set the values accordingly
	for (int i = 0; i < SZG_MAX_DNA_RANGES - 1; i++) {
		uint16_t vio;
		vio = dna_json["vio"][i]["min"].get<uint16_t>();
		dna_header[SZG_DNA_MIN_VIO_RANGE0 + 4*i] = vio & 0xFF;
		dna_header[SZG_DNA_MIN_VIO_RANGE0 + (4*i) + 1] = (vio & 0xFF00) >> 8;

		vio = dna_json["vio"][i]["max"].get<uint16_t>();
		dna_header[SZG_DNA_MAX_VIO_RANGE0 + 4*i] = vio & 0xFF;
		dna_header[SZG_DNA_MAX_VIO_RANGE0 + (4*i) + 1] = (vio & 0xFF00) >> 8;
	}

	uint8_t manuf_len =
	    dna_json["manufacturer_name"].get<std::string>().length();

	uint8_t name_len =
	    dna_json["product_name"].get<std::string>().length();

	uint8_t model_len =
	    dna_json["product_model"].get<std::string>().length();

	uint8_t version_len =
	    dna_json["product_version"].get<std::string>().length();

	uint8_t serial_len = 0;

	if (argc == 4) {
		serial_len = strlen(argv[3]);
	} else {
		serial_len = dna_json["serial"].get<std::string>().length();
	}

	dna_header[SZG_DNA_MANUFACTURER_NAME_LENGTH] = manuf_len;

	dna_header[SZG_DNA_PRODUCT_NAME_LENGTH] = name_len;

	dna_header[SZG_DNA_PRODUCT_MODEL_LENGTH] = model_len;

	dna_header[SZG_DNA_PRODUCT_VERSION_LENGTH] = version_len;

	dna_header[SZG_DNA_SERIAL_NUMBER_LENGTH] = serial_len;

	uint16_t dna_length = SZG_DNA_HEADER_LENGTH_V1 + manuf_len + name_len +
	                      model_len + version_len + serial_len;

	dna_header[SZG_DNA_PTR_FULL_LENGTH] = dna_length & 0xFF;
	dna_header[SZG_DNA_PTR_FULL_LENGTH + 1] = (dna_length & 0xFF00) >> 8;

	// Calculate and insert the CRC once all data has been gathered
	uint16_t crc = szgComputeCRC(&dna_header[0], SZG_DNA_HEADER_LENGTH_V1 - 2);

	dna_header[SZG_DNA_CRC16_HIGH] = (crc & 0xFF00) >> 8;
	dna_header[SZG_DNA_CRC16_LOW] = crc & 0xFF;

	for (int i = 0; i < SZG_DNA_HEADER_LENGTH_V1; i++) {
		output_file << dna_header[i];
	}

	output_file << dna_json["manufacturer_name"].get<std::string>();
	output_file << dna_json["product_name"].get<std::string>();
	output_file << dna_json["product_model"].get<std::string>();
	output_file << dna_json["product_version"].get<std::string>();

	if (argc == 4) {
		output_file << argv[3];
	} else {
		output_file << dna_json["serial"].get<std::string>();
	}

	return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x458, %rsp            # imm = 0x458
movq %rsi, %r14
movl %edi, %ebx
movl $0x28, %edi
callq 0x3240
leal -0x5(%rbx), %ecx
xorps %xmm0, %xmm0
movups %xmm0, (%rax)
movups %xmm0, 0x10(%rax)
movq %rax, 0x8(%rsp)
movq $0x0, 0x20(%rax)
cmpl $-0x3, %ecx
ja 0x3731
movq 0xa8e6(%rip), %rbx      # 0xdfd8
leaq 0x5e2b(%rip), %rsi      # 0x9524
movl $0x7, %edx
movq %rbx, %rdi
callq 0x3290
movq (%r14), %r14
testq %r14, %r14
je 0x3d13
movq %r14, %rdi
callq 0x3120
movq 0xa8b7(%rip), %rdi      # 0xdfd8
movq %r14, %rsi
movq %rax, %rdx
callq 0x3290
jmp 0x3d2a
movq 0x8(%r14), %rsi
leaq 0x250(%rsp), %rdi
movl $0x8, %edx
callq 0x33b0
movq 0x10(%r14), %rsi
leaq 0x50(%rsp), %rdi
movl $0x14, %edx
callq 0x3270
movq %rbx, 0x48(%rsp)
movq %r14, 0x40(%rsp)
leaq 0x30(%rsp), %rbx
movb $0x0, (%rbx)
movq $0x0, 0x8(%rbx)
movq %rbx, %rdi
callq 0x4386
movq %rbx, %rdi
callq 0x4386
leaq 0x250(%rsp), %rdi
movq %rbx, %rsi
callq 0x3e6f
movq 0x8(%rsp), %rax
movl $0x1010028, 0x2(%rax)   # imm = 0x1010028
leaq 0x5dec(%rip), %rsi      # 0x9593
leaq 0x30(%rsp), %rdi
callq 0x3ff4
leaq 0x10(%rsp), %rsi
movq %rax, %rdi
callq 0x7b2e
movb 0x10(%rsp), %al
movq 0x8(%rsp), %rcx
movb %al, 0x6(%rcx)
movb %al, 0x7(%rcx)
leaq 0x5dc7(%rip), %rsi      # 0x959b
leaq 0x30(%rsp), %rdi
callq 0x3ff4
leaq 0x10(%rsp), %rsi
movq %rax, %rdi
callq 0x7c18
movb 0x10(%rsp), %al
movq 0x8(%rsp), %rcx
movb %al, 0x8(%rcx)
leaq 0x5d9d(%rip), %rsi      # 0x959b
leaq 0x30(%rsp), %rdi
callq 0x3ff4
leaq 0x10(%rsp), %rsi
movq %rax, %rdi
callq 0x7c18
movb 0x11(%rsp), %al
movq 0x8(%rsp), %rcx
movb %al, 0x9(%rcx)
leaq 0x5d7f(%rip), %rsi      # 0x95a7
leaq 0x30(%rsp), %rdi
callq 0x3ff4
leaq 0x10(%rsp), %rsi
movq %rax, %rdi
callq 0x7c18
movb 0x10(%rsp), %al
movq 0x8(%rsp), %rcx
movb %al, 0xa(%rcx)
leaq 0x5d55(%rip), %rsi      # 0x95a7
leaq 0x30(%rsp), %rdi
callq 0x3ff4
leaq 0x10(%rsp), %rsi
movq %rax, %rdi
callq 0x7c18
movb 0x11(%rsp), %al
movq 0x8(%rsp), %rcx
movb %al, 0xb(%rcx)
leaq 0x5d38(%rip), %rsi      # 0x95b4
leaq 0x30(%rsp), %rdi
callq 0x3ff4
leaq 0x10(%rsp), %rsi
movq %rax, %rdi
callq 0x7c18
movb 0x10(%rsp), %al
movq 0x8(%rsp), %rcx
movb %al, 0xc(%rcx)
leaq 0x5d0e(%rip), %rsi      # 0x95b4
leaq 0x30(%rsp), %rdi
callq 0x3ff4
leaq 0x10(%rsp), %rsi
movq %rax, %rdi
callq 0x7c18
movb 0x11(%rsp), %al
movq 0x8(%rsp), %rcx
movb %al, 0xd(%rcx)
leaq 0x5cf1(%rip), %rsi      # 0x95c1
leaq 0x30(%rsp), %rdi
callq 0x3ff4
leaq 0x10(%rsp), %rsi
movq %rax, %rdi
callq 0x7b2e
movb 0x10(%rsp), %al
movq 0x8(%rsp), %rcx
orb %al, 0xe(%rcx)
leaq 0x5ccf(%rip), %rsi      # 0x95c9
leaq 0x30(%rsp), %rdi
callq 0x3ff4
leaq 0x10(%rsp), %rsi
movq %rax, %rdi
callq 0x7b2e
movb 0x10(%rsp), %al
addb %al, %al
movq 0x8(%rsp), %rcx
orb %al, 0xe(%rcx)
leaq 0x5c6d(%rip), %rsi      # 0x9593
leaq 0x30(%rsp), %rdi
callq 0x3ff4
leaq 0x10(%rsp), %rsi
movq %rax, %rdi
callq 0x7b2e
leaq 0x10(%rsp), %r12
movb (%r12), %al
shlb $0x2, %al
movq 0x8(%rsp), %rcx
orb %al, 0xe(%rcx)
xorl %r13d, %r13d
leaq 0x5c7c(%rip), %rbp      # 0x95d7
leaq 0x30(%rsp), %r14
leaq 0x5c74(%rip), %r15      # 0x95db
leaq 0x5c71(%rip), %rbx      # 0x95df
movq %r14, %rdi
movq %rbp, %rsi
callq 0x3ff4
movq %rax, %rdi
movq %r13, %rsi
callq 0x4176
movq %rax, %rdi
movq %r15, %rsi
callq 0x3ff4
movq %rax, %rdi
movq %r12, %rsi
callq 0x7c18
movzwl 0x10(%rsp), %eax
movq 0x8(%rsp), %rcx
movw %ax, 0x10(%rcx,%r13,4)
movq %r14, %rdi
movq %rbp, %rsi
callq 0x3ff4
movq %rax, %rdi
movq %r13, %rsi
callq 0x4176
movq %rax, %rdi
movq %rbx, %rsi
callq 0x3ff4
movq %rax, %rdi
movq %r12, %rsi
callq 0x7c18
movzwl 0x10(%rsp), %eax
movq 0x8(%rsp), %rcx
movw %ax, 0x12(%rcx,%r13,4)
incq %r13
cmpq $0x3, %r13
jne 0x396e
leaq 0x5be9(%rip), %rsi      # 0x95e3
leaq 0x30(%rsp), %rdi
callq 0x3ff4
leaq 0x10(%rsp), %rdi
movq %rax, %rsi
callq 0x4310
leaq 0x20(%rsp), %r15
movq -0x10(%r15), %rdi
movq -0x8(%r15), %r14
cmpq %r15, %rdi
je 0x3a28
callq 0x3220
leaq 0x5bc6(%rip), %rsi      # 0x95f5
leaq 0x30(%rsp), %rdi
callq 0x3ff4
leaq 0x10(%rsp), %rdi
movq %rax, %rsi
callq 0x4310
movq 0x10(%rsp), %rdi
movq 0x18(%rsp), %r12
cmpq %r15, %rdi
je 0x3a5a
callq 0x3220
leaq 0x5ba1(%rip), %rsi      # 0x9602
leaq 0x30(%rsp), %rdi
callq 0x3ff4
leaq 0x10(%rsp), %rdi
movq %rax, %rsi
callq 0x4310
movq 0x10(%rsp), %rdi
movq 0x18(%rsp), %r13
cmpq %r15, %rdi
je 0x3a8c
callq 0x3220
leaq 0x5b7d(%rip), %rsi      # 0x9610
leaq 0x30(%rsp), %rdi
callq 0x3ff4
leaq 0x10(%rsp), %rdi
movq %rax, %rsi
callq 0x4310
movq 0x10(%rsp), %rdi
movq 0x18(%rsp), %rbp
cmpq %r15, %rdi
je 0x3abe
callq 0x3220
cmpl $0x4, 0x48(%rsp)
jne 0x3ad8
movq 0x40(%rsp), %rax
movq 0x18(%rax), %rdi
callq 0x3120
movq %rax, %rbx
jmp 0x3b0a
leaq 0x5b41(%rip), %rsi      # 0x9620
leaq 0x30(%rsp), %rdi
callq 0x3ff4
leaq 0x10(%rsp), %rdi
movq %rax, %rsi
callq 0x4310
movq 0x10(%rsp), %rdi
movq 0x18(%rsp), %rbx
cmpq %r15, %rdi
je 0x3b0a
callq 0x3220
movq 0x8(%rsp), %rdi
movb %r14b, 0x20(%rdi)
movb %r12b, 0x21(%rdi)
movb %r13b, 0x22(%rdi)
movb %bpl, 0x23(%rdi)
movb %bl, 0x24(%rdi)
movl $0xff, %eax
andl %eax, %r14d
andl %eax, %r12d
addl %r14d, %r12d
andl %eax, %r13d
andl %eax, %ebp
addl %r13d, %ebp
addl %r12d, %ebp
andl %eax, %ebx
leal (%rbx,%rbp), %eax
addl $0x28, %eax
movb %al, (%rdi)
movb %ah, 0x1(%rdi)
movl $0x26, %esi
callq 0x86c4
rolw $0x8, %ax
movq 0x8(%rsp), %rcx
movw %ax, 0x26(%rcx)
xorl %r12d, %r12d
leaq 0x50(%rsp), %rbx
leaq 0x10(%rsp), %r14
movq 0x8(%rsp), %rax
movb (%rax,%r12), %al
movb %al, 0x10(%rsp)
movl $0x1, %edx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x3290
incq %r12
cmpq $0x28, %r12
jne 0x3b6c
leaq 0x5a4a(%rip), %rsi      # 0x95e3
leaq 0x30(%rsp), %rdi
callq 0x3ff4
leaq 0x10(%rsp), %rdi
movq %rax, %rsi
callq 0x4310
movq 0x10(%rsp), %rsi
movq 0x18(%rsp), %rdx
leaq 0x50(%rsp), %rdi
callq 0x3290
movq 0x10(%rsp), %rdi
cmpq %r15, %rdi
je 0x3bd3
callq 0x3220
leaq 0x5a1b(%rip), %rsi      # 0x95f5
leaq 0x30(%rsp), %rdi
callq 0x3ff4
leaq 0x10(%rsp), %rdi
movq %rax, %rsi
callq 0x4310
movq 0x10(%rsp), %rsi
movq 0x18(%rsp), %rdx
leaq 0x50(%rsp), %rdi
callq 0x3290
movq 0x10(%rsp), %rdi
cmpq %r15, %rdi
je 0x3c14
callq 0x3220
leaq 0x59e7(%rip), %rsi      # 0x9602
leaq 0x30(%rsp), %rdi
callq 0x3ff4
leaq 0x10(%rsp), %rdi
movq %rax, %rsi
callq 0x4310
movq 0x10(%rsp), %rsi
movq 0x18(%rsp), %rdx
leaq 0x50(%rsp), %rdi
callq 0x3290
movq 0x10(%rsp), %rdi
cmpq %r15, %rdi
je 0x3c55
callq 0x3220
leaq 0x59b4(%rip), %rsi      # 0x9610
leaq 0x30(%rsp), %rdi
callq 0x3ff4
leaq 0x10(%rsp), %rdi
movq %rax, %rsi
callq 0x4310
movq 0x10(%rsp), %rsi
movq 0x18(%rsp), %rdx
leaq 0x50(%rsp), %rdi
callq 0x3290
movq 0x10(%rsp), %rdi
cmpq %r15, %rdi
je 0x3c96
callq 0x3220
cmpl $0x4, 0x48(%rsp)
jne 0x3ccc
movq 0x40(%rsp), %rax
movq 0x18(%rax), %rbx
testq %rbx, %rbx
je 0x3d74
movq %rbx, %rdi
callq 0x3120
leaq 0x50(%rsp), %rdi
movq %rbx, %rsi
movq %rax, %rdx
callq 0x3290
jmp 0x3d90
leaq 0x594d(%rip), %rsi      # 0x9620
leaq 0x30(%rsp), %rdi
callq 0x3ff4
leaq 0x10(%rsp), %rdi
movq %rax, %rsi
callq 0x4310
movq 0x10(%rsp), %rsi
movq 0x18(%rsp), %rdx
leaq 0x50(%rsp), %rdi
callq 0x3290
movq 0x10(%rsp), %rdi
cmpq %r15, %rdi
je 0x3d90
callq 0x3220
jmp 0x3d90
movq (%rbx), %rax
movq -0x18(%rax), %rax
leaq (%rbx,%rax), %rdi
movl 0x20(%rbx,%rax), %esi
orl $0x1, %esi
callq 0x3360
movq 0xa2a7(%rip), %rdi      # 0xdfd8
leaq 0x57f4(%rip), %rsi      # 0x952c
movl $0x1b, %edx
callq 0x3290
movq 0xa28f(%rip), %rdi      # 0xdfd8
leaq 0x57f8(%rip), %rsi      # 0x9548
movl $0x26, %edx
callq 0x3290
movq 0xa277(%rip), %rdi      # 0xdfd8
leaq 0x5807(%rip), %rsi      # 0x956f
movl $0x23, %edx
callq 0x3290
jmp 0x3dd9
movq 0x50(%rsp), %rax
movq -0x18(%rax), %rax
leaq (%rsp,%rax), %rdi
addq $0x50, %rdi
movl 0x20(%rdi), %esi
orl $0x1, %esi
callq 0x3360
leaq 0x30(%rsp), %rdi
callq 0x4358
movq 0xa227(%rip), %rax      # 0xdfc8
movq (%rax), %rcx
movq 0x18(%rax), %rax
leaq 0x58(%rsp), %rdi
movq %rcx, -0x8(%rdi)
movq -0x18(%rcx), %rcx
movq %rax, 0x50(%rsp,%rcx)
callq 0x31f0
leaq 0x148(%rsp), %rdi
callq 0x30c0
leaq 0x250(%rsp), %rdi
callq 0x3080
movq 0x8(%rsp), %rdi
callq 0x3220
xorl %eax, %eax
addq $0x458, %rsp            # imm = 0x458
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x3e01
jmp 0x3e39
jmp 0x3e01
jmp 0x3e01
jmp 0x3e01
movq %rax, %r14
movq 0x10(%rsp), %rdi
cmpq %r15, %rdi
je 0x3e3c
callq 0x3220
jmp 0x3e3c
jmp 0x3e39
movq %rax, %r14
jmp 0x3e50
jmp 0x3e30
jmp 0x3e39
jmp 0x3e39
jmp 0x3e39
jmp 0x3e39
jmp 0x3e39
jmp 0x3e39
jmp 0x3e39
jmp 0x3e39
jmp 0x3e39
movq %rax, %r14
jmp 0x3e5d
jmp 0x3e39
jmp 0x3e39
movq %rax, %r14
leaq 0x30(%rsp), %rdi
callq 0x4358
leaq 0x50(%rsp), %rdi
callq 0x3300
leaq 0x250(%rsp), %rdi
callq 0x3080
movq 0x8(%rsp), %rdi
callq 0x3220
movq %r14, %rdi
callq 0x3390