// File: /workspace/github_c_makefile_star2_O3/jsummers[P]deark/modules/macbinary.c
// Function: de_identify_macbinary
static int de_identify_macbinary(deark *c)
{
	int conf = 0;
	int k;
	int has_sig;
	int is_v23 = 0; // v2 or v3
	int good_file_len = 0;
	int good_cc = 0;
	int bad_crc = 0;
	int fnlen;
	i64 n;
	i64 dflen, rflen;
	i64 min_expected_len;
	u32 crc_reported, crc_calc;
	u8 b[128];

	// "old" version number is always 0.
	b[0] = de_getbyte(0);
	if(b[0]!=0) goto done;

	// filename length
	b[1] = de_getbyte(1);
	if(b[1]<1 || b[1]>63) goto done;

	de_read(&b[2], 2, sizeof(b)-2);

	if(b[2]==0) goto done; // First filename byte
	if(b[74]!=0) goto done;
	if(b[82]!=0) goto done;

	// Extended version number
	if(b[122]==129 && b[123]==129) {
		// v2
		is_v23 = 1;
	}
	else if(b[122]==130 && (b[123]==129 || b[123]==130)) {
		// v3
		is_v23 = 1;
	}
	// else v1.
	// Some v1 files have garbage in the last 29 bytes of the file,
	// so we can't assume the extended version number is 0.

	// Ver.III signature, but possibly used in some files that have earlier
	// version numbers.
	has_sig = !de_memcmp(&b[102], (const void*)"mBIN", 4);
	if(has_sig) {
		conf = 90;
		goto done;
	}

	// Check if filename characters are sensible
	fnlen = (int)b[1];
	for(k=0; k<fnlen; k++) {
		if(b[2+k]>0 && b[2+k]<32) {
			// Control char found.

			if(b[2+k]==0x0d && fnlen>1 && k==fnlen-1) {
				// Exception: Allow the last char to be a CR.
				;
			}
			else {
				goto done;
			}
		}
	}

	// File type code. Expect ASCII.
	good_cc = 1;
	for(k=65; k<=68; k++) {
		if(b[k]<32 || b[k]>127) good_cc = 0;
	}

	dflen = de_getu32be_direct(&b[83]);
	rflen = de_getu32be_direct(&b[87]);

	crc_reported = (u32)de_getu16be_direct(&b[124]);

	// Check the file size.

	// Resource forks that go beyond the end of file are too common to
	// disallow.
	if(128 + dflen > c->infile->len) goto done;
	if(128 + rflen + dflen > c->infile->len + 4096) goto done;

	if(rflen>0) {
		min_expected_len = 128 + de_pad_to_n(dflen, 128) + rflen;
	}
	else {
		min_expected_len = 128 + dflen;
	}

	// The file size really should be exactly min_expected_len, or that
	// number padded to the next multiple of 128. But I'm not bold
	// enough to require it.
	if((c->infile->len == min_expected_len) ||
		(c->infile->len == de_pad_to_n(min_expected_len, 128)))
	{
		good_file_len = 1;
	}

	if(is_v23) {
		// Most MacBinary II specific checks go here

		if(!de_is_all_zeroes(&b[102], 14)) {
			if(!good_file_len) goto done;
		}

		// Secondary header length. We don't support this.
		n = de_getu16be_direct(&b[120]);
		if(n!=0) goto done;
	}
	else {
		// Most Original MacBinary format checks go here

		// An empty file is not illegal, but we need as many checks as possible
		// that won't be passed by all 0 bytes.
		if(dflen==0 && rflen==0) goto done;

		// Unused fields in this version should be all 0, though we'll allow
		// nonzero values in some cases.
		if(!de_is_all_zeroes(&b[99], 25)) {
			if(!good_file_len) goto done;
		}
	}

	if(crc_reported!=0 || is_v23) {
		struct de_crcobj *crco;

		crco = de_crcobj_create(c, DE_CRCOBJ_CRC16_XMODEM);
		de_crcobj_addbuf(crco, b, 124);
		crc_calc = de_crcobj_getval(crco);
		de_crcobj_destroy(crco);
		if(crc_calc!=crc_reported && is_v23 && crc_reported!=0) {
			bad_crc = 1;
		}
	}

	if(is_v23 && good_file_len && good_cc) {
		if(bad_crc) {
			conf = 19;
		}
		else {
			conf = 90;
		}
	}
	else if(bad_crc) {
		goto done;
	}
	else if(is_v23) {
		conf = 49;
	}
	else if(good_cc) {
		conf = 29;
	}
	else {
		conf = 19;
	}

done:
	if(conf>0) {
		c->detection_data->is_macbinary = 1;
	}
	return conf;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xa8, %rsp
movq %rdi, %rbx
movq 0x18(%rdi), %rdi
xorl %esi, %esi
callq 0xeead3
movb %al, 0x20(%rsp)
testb %al, %al
jne 0x8ea9f
movq 0x18(%rbx), %rdi
movl $0x1, %esi
callq 0xeead3
movb %al, 0x21(%rsp)
addb $-0x40, %al
cmpb $-0x3f, %al
jae 0x8eab3
xorl %eax, %eax
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x18(%rbx), %rdi
leaq 0x22(%rsp), %r14
movl $0x2, %edx
movl $0x7e, %ecx
movq %r14, %rsi
callq 0xee8d4
cmpb $0x0, (%r14)
je 0x8ea9f
cmpb $0x0, 0x6a(%rsp)
jne 0x8ea9f
cmpb $0x0, 0x72(%rsp)
jne 0x8ea9f
movb 0x9a(%rsp), %cl
movb 0x9b(%rsp), %al
movl %ecx, %edx
xorb $-0x7f, %dl
movl %eax, %esi
xorb $-0x7f, %sil
movb $0x1, %r13b
orb %dl, %sil
je 0x8eb14
cmpb $-0x7e, %cl
sete %cl
addb $0x7f, %al
cmpb $0x2, %al
setb %r13b
andb %cl, %r13b
cmpl $0x4e49426d, 0x86(%rsp) # imm = 0x4E49426D
je 0x8ec31
movzbl 0x21(%rsp), %ecx
testq %rcx, %rcx
je 0x8eb66
leal -0x1(%rcx), %edx
xorl %esi, %esi
movb 0x22(%rsp,%rsi), %dil
leal -0x1(%rdi), %eax
cmpb $0x1e, %al
ja 0x8eb5e
xorl %eax, %eax
cmpl $0x1, %ecx
je 0x8eaa1
cmpb $0xd, %dil
jne 0x8eaa1
cmpq %rsi, %rdx
jne 0x8eaa1
incq %rsi
cmpq %rsi, %rcx
jne 0x8eb34
leaq 0x73(%rsp), %rdi
movl -0x12(%rdi), %r14d
callq 0xeed08
movq %rax, %r15
leaq 0x77(%rsp), %rdi
callq 0xeed08
movq %rax, %r12
leaq 0x9c(%rsp), %rdi
callq 0xeeb5c
leaq 0x80(%r15), %rdi
movq 0x18(%rbx), %rcx
movq 0x18(%rcx), %rbp
cmpq %rbp, %rdi
jg 0x8ea9f
movq %rax, 0x8(%rsp)
leaq (%rdi,%r12), %rax
leaq 0x1000(%rbp), %rcx
cmpq %rcx, %rax
jg 0x8ea9f
movd %r14d, %xmm0
movdqa 0x9fce1(%rip), %xmm1    # 0x12e8b0
punpcklbw %xmm1, %xmm1    # xmm1 = xmm1[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7]
punpcklwd %xmm1, %xmm1    # xmm1 = xmm1[0,0,1,1,2,2,3,3]
punpcklbw %xmm0, %xmm0    # xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7]
punpcklwd %xmm0, %xmm0    # xmm0 = xmm0[0,0,1,1,2,2,3,3]
pcmpgtb %xmm0, %xmm1
testq %r12, %r12
jle 0x8ec14
movl $0x80, %esi
movq %r15, %rdi
movdqa %xmm1, 0x10(%rsp)
callq 0xe9cb4
movdqa 0x10(%rsp), %xmm1
leaq (%r12,%rax), %rdi
addq $0x80, %rdi
movq 0x18(%rbx), %rax
movq 0x18(%rax), %rbp
movmskps %xmm1, %r14d
cmpq %rdi, %rbp
je 0x8ec2c
movl $0x80, %esi
callq 0xe9cb4
cmpq %rax, %rbp
jne 0x8ec43
movb $0x1, %bpl
jmp 0x8ec45
movl $0x5a, %eax
movq 0x28(%rbx), %rcx
movb $0x1, 0x4(%rcx)
jmp 0x8eaa1
xorl %ebp, %ebp
testb %r13b, %r13b
je 0x8ec90
leaq 0x86(%rsp), %rdi
movl $0xe, %esi
callq 0xf1838
testl %eax, %eax
sete %al
movl %ebp, %ecx
notb %cl
testb %al, %cl
jne 0x8ea9f
leaq 0x98(%rsp), %rdi
callq 0xeeb5c
testq %rax, %rax
jne 0x8ea9f
movq 0x8(%rsp), %rax
testl %eax, %eax
setne %r12b
jmp 0x8eccc
orq %r12, %r15
je 0x8ea9f
leaq 0x83(%rsp), %rdi
movl $0x19, %esi
callq 0xf1838
testl %eax, %eax
sete %al
movl %ebp, %ecx
notb %cl
testb %al, %cl
jne 0x8ea9f
movb $0x1, %r12b
movq 0x8(%rsp), %rax
testl %eax, %eax
je 0x8ed4e
movq %rbx, %rdi
movl $0x20, %esi
movl %r14d, 0x8(%rsp)
movq %rax, %r14
callq 0xeb499
movq %rax, %r15
leaq 0x20(%rsp), %rsi
movl $0x7c, %edx
movq %rax, %rdi
callq 0xeb8ad
movq %r15, %rdi
callq 0xeb865
movl %eax, 0x10(%rsp)
movq %r15, %rdi
callq 0xeb858
cmpl %r14d, 0x10(%rsp)
movl 0x8(%rsp), %r14d
setne %al
andb %r13b, %r12b
andb %al, %r12b
andb %r13b, %bpl
cmpb $0x1, %bpl
jne 0x8ed40
testb %r14b, %r14b
jne 0x8ed40
testb %r12b, %r12b
movl $0x13, %ecx
movl $0x5a, %eax
cmovnel %ecx, %eax
jmp 0x8ec36
movl $0x0, %eax
testb %r12b, %r12b
jne 0x8eaa1
testb %r14b, %r14b
movl $0x1d, %eax
movl $0x13, %ecx
cmovel %eax, %ecx
testb %r13b, %r13b
movl $0x31, %eax
cmovel %ecx, %eax
jmp 0x8ec36