// File: /workspace/github_c_makefile_star2_O2/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 %r14d, %r14d
xorl %esi, %esi
callq 0xe3eb4
movb %al, 0x20(%rsp)
testb %al, %al
jne 0x897b5
movq 0x18(%rbx), %rdi
pushq $0x1
popq %rsi
callq 0xe3eb4
movb %al, 0x21(%rsp)
addb $-0x40, %al
cmpb $-0x3f, %al
jae 0x897ca
movl %r14d, %eax
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x18(%rbx), %rdi
leaq 0x22(%rsp), %r15
pushq $0x2
popq %rdx
pushq $0x7e
popq %rcx
movq %r15, %rsi
callq 0xe3cb7
cmpb $0x0, (%r15)
je 0x897b5
cmpb $0x0, 0x6a(%rsp)
jne 0x897b5
cmpb $0x0, 0x72(%rsp)
jne 0x897b5
movb 0x9a(%rsp), %cl
movb 0x9b(%rsp), %al
movl %ecx, %edx
xorb $-0x7f, %dl
movl %eax, %esi
xorb $-0x7f, %sil
movb $0x1, %r8b
orb %dl, %sil
je 0x89827
cmpb $-0x7e, %cl
sete %cl
addb $0x7f, %al
cmpb $0x2, %al
setb %r8b
andb %cl, %r8b
cmpl $0x4e49426d, 0x86(%rsp) # imm = 0x4E49426D
je 0x8993f
leaq 0x86(%rsp), %rax
movzbl -0x65(%rax), %eax
movl %eax, %ecx
decl %ecx
xorl %edx, %edx
cmpq %rdx, %rax
je 0x89880
movb 0x22(%rsp,%rdx), %sil
leal -0x1(%rsi), %edi
cmpb $0x1e, %dil
ja 0x8987b
xorl %r14d, %r14d
cmpb $0x2, %al
jb 0x897b5
cmpb $0xd, %sil
jne 0x897b5
cmpq %rdx, %rcx
jne 0x897b5
incq %rdx
jmp 0x8984a
pushq $0x1
popq %r15
pushq $0x41
popq %rax
xorl %ecx, %ecx
cmpq $0x45, %rax
je 0x8989d
cmpb $0x20, 0x20(%rsp,%rax)
cmovll %ecx, %r15d
incq %rax
jmp 0x89889
movb %r8b, 0xb(%rsp)
leaq 0x73(%rsp), %rdi
callq 0xe404a
movq %rax, %r13
leaq 0x77(%rsp), %rdi
callq 0xe404a
movq %rax, %rbp
leaq 0x9c(%rsp), %rdi
callq 0xe3f3b
leaq 0x80(%r13), %rdi
movq 0x18(%rbx), %rcx
movq 0x18(%rcx), %r12
xorl %r14d, %r14d
cmpq %r12, %rdi
jg 0x897b5
movq %rax, 0x10(%rsp)
leaq (%rdi,%rbp), %rax
leaq 0x1000(%r12), %rcx
cmpq %rcx, %rax
jg 0x897b5
testq %rbp, %rbp
jle 0x89923
movl $0x80, %esi
movq %r13, %rdi
callq 0xdfbb6
leaq (%rax,%rbp), %rdi
addq $0x80, %rdi
movq 0x18(%rbx), %rax
movq 0x18(%rax), %r12
cmpq %rdi, %r12
je 0x89937
movl $0x80, %esi
callq 0xdfbb6
cmpq %rax, %r12
jne 0x89950
movb $0x1, %al
movl %eax, 0xc(%rsp)
jmp 0x89958
pushq $0x5a
popq %r14
movq 0x28(%rbx), %rax
movb $0x1, 0x4(%rax)
jmp 0x897b5
movl $0x0, 0xc(%rsp)
movb 0xb(%rsp), %r12b
testb %r12b, %r12b
je 0x899a8
pushq $0xe
popq %rsi
leaq 0x86(%rsp), %rdi
callq 0xe66b4
testl %eax, %eax
sete %al
movl 0xc(%rsp), %ecx
notb %cl
testb %al, %cl
jne 0x897b5
leaq 0x98(%rsp), %rdi
callq 0xe3f3b
testq %rax, %rax
jne 0x897b5
movq 0x10(%rsp), %rax
testl %eax, %eax
setne %bpl
jmp 0x899e0
orq %rbp, %r13
je 0x897b5
leaq 0x83(%rsp), %rdi
pushq $0x19
popq %rsi
callq 0xe66b4
testl %eax, %eax
sete %al
movl 0xc(%rsp), %ecx
notb %cl
testb %al, %cl
jne 0x897b5
movb $0x1, %bpl
movq 0x10(%rsp), %rax
testl %eax, %eax
je 0x89a58
pushq $0x20
popq %rsi
movq %rbx, %rdi
callq 0xe0ae9
movq %rax, %r13
leaq 0x20(%rsp), %rsi
pushq $0x7c
popq %rdx
movq %rax, %rdi
callq 0xe0ecf
movq %r13, %rdi
callq 0xe0e95
movl %eax, 0x1c(%rsp)
movq %r13, %rdi
callq 0xe0e8d
movl 0x1c(%rsp), %eax
cmpl 0x10(%rsp), %eax
setne %al
andb %r12b, %bpl
andb %al, %bpl
movl 0xc(%rsp), %ecx
andb %r12b, %cl
testl %r15d, %r15d
setne %al
cmpb $0x1, %cl
jne 0x89a4d
testl %r15d, %r15d
je 0x89a4d
testb %bpl, %bpl
pushq $0x13
popq %rax
pushq $0x5a
popq %r14
cmovnel %eax, %r14d
jmp 0x89943
testb %bpl, %bpl
jne 0x897b5
jmp 0x89a5e
testl %r15d, %r15d
setne %al
testb %al, %al
pushq $0x1d
popq %rax
pushq $0x13
popq %rcx
cmovnel %eax, %ecx
testb %r12b, %r12b
pushq $0x31
popq %r14
cmovel %ecx, %r14d
jmp 0x89943