// File: /workspace/github_c_makefile_star2_O1/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 $0x98, %rsp
movq %rdi, %rbx
movq 0x18(%rdi), %rdi
xorl %ebp, %ebp
xorl %esi, %esi
callq 0xef0d5
movl %eax, %ecx
movb %al, 0x10(%rsp)
movl $0x0, %eax
testb %cl, %cl
jne 0x8f538
movq 0x18(%rbx), %rdi
movl $0x1, %esi
callq 0xef0d5
movl %eax, %ecx
movb %al, 0x11(%rsp)
addb $-0x40, %cl
xorl %ebp, %ebp
movl $0x0, %eax
cmpb $-0x3f, %cl
jb 0x8f538
movq 0x18(%rbx), %rdi
leaq 0x12(%rsp), %r14
movl $0x2, %edx
movl $0x7e, %ecx
movq %r14, %rsi
callq 0xeeee8
xorl %ebp, %ebp
cmpb $0x0, (%r14)
je 0x8f52f
cmpb $0x0, 0x5a(%rsp)
jne 0x8f52f
cmpb $0x0, 0x62(%rsp)
movl $0x0, %eax
jne 0x8f538
movb 0x8a(%rsp), %cl
movb 0x8b(%rsp), %al
movl %ecx, %edx
xorb $-0x7f, %dl
movl %eax, %esi
xorb $-0x7f, %sil
movb $0x1, %bpl
orb %dl, %sil
movb $0x1, %r14b
je 0x8f41e
cmpb $-0x7e, %cl
sete %cl
addb $0x7f, %al
cmpb $0x2, %al
setb %r14b
andb %cl, %r14b
cmpl $0x4e49426d, 0x76(%rsp) # imm = 0x4E49426D
je 0x8f533
movzbl 0x11(%rsp), %ecx
testq %rcx, %rcx
je 0x8f471
leal -0x1(%rcx), %edx
xorl %esi, %esi
movb 0x12(%rsp,%rsi), %al
leal -0x1(%rax), %edi
cmpb $0x1e, %dil
ja 0x8f469
xorl %ebp, %ebp
cmpl $0x1, %ecx
je 0x8f52f
cmpb $0xd, %al
jne 0x8f52f
movl $0x0, %eax
cmpq %rsi, %rdx
jne 0x8f538
incq %rsi
cmpq %rsi, %rcx
jne 0x8f43b
movl $0x1, %r15d
movl $0x41, %eax
xorl %ecx, %ecx
cmpb $0x20, 0x10(%rsp,%rax)
cmovll %ecx, %r15d
incq %rax
cmpq $0x45, %rax
jne 0x8f47e
leaq 0x63(%rsp), %rdi
callq 0xef325
movq %rax, %r12
leaq 0x67(%rsp), %rdi
callq 0xef325
movq %rax, %r13
leaq 0x8c(%rsp), %rdi
callq 0xef15e
movq %rax, 0x8(%rsp)
leaq 0x80(%r12), %rdi
movq 0x18(%rbx), %rax
movq 0x18(%rax), %rcx
xorl %ebp, %ebp
movl $0x0, %eax
cmpq %rcx, %rdi
jg 0x8f538
leaq (%r12,%r13), %rdx
addq $0x80, %rdx
addq $0x1000, %rcx           # imm = 0x1000
xorl %ebp, %ebp
cmpq %rcx, %rdx
jg 0x8f538
testq %r13, %r13
jle 0x8f50e
movl $0x80, %esi
movq %r12, %rdi
callq 0xea80b
leaq (%rax,%r13), %rdi
addq $0x80, %rdi
movq 0x18(%rbx), %rax
movq 0x18(%rax), %rbp
cmpq %rdi, %rbp
je 0x8f52a
movl $0x80, %esi
callq 0xea80b
cmpq %rax, %rbp
jne 0x8f557
movb $0x1, %bpl
jmp 0x8f559
xorl %eax, %eax
jmp 0x8f538
movl $0x5a, %eax
testb %bpl, %bpl
je 0x8f545
movq 0x28(%rbx), %rcx
movb $0x1, 0x4(%rcx)
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
xorl %ebp, %ebp
testb %r14b, %r14b
movl %ebp, 0x4(%rsp)
je 0x8f5a3
movl $0xe, %esi
leaq 0x76(%rsp), %rdi
callq 0xf1edd
testl %eax, %eax
sete %cl
movl %ebp, %edx
notb %dl
xorl %ebp, %ebp
movl $0x0, %eax
testb %cl, %dl
jne 0x8f538
leaq 0x88(%rsp), %rdi
callq 0xef15e
movq %rax, %rcx
xorl %ebp, %ebp
movl $0x0, %eax
testq %rcx, %rcx
jne 0x8f538
jmp 0x8f5da
xorl %ebp, %ebp
orq %r13, %r12
movl $0x0, %eax
je 0x8f538
leaq 0x73(%rsp), %rdi
movl $0x19, %esi
callq 0xf1edd
testl %eax, %eax
sete %cl
movl 0x4(%rsp), %eax
movl %eax, %edx
notb %dl
xorl %ebp, %ebp
movl $0x0, %eax
testb %cl, %dl
jne 0x8f538
movq 0x8(%rsp), %rbp
testl %ebp, %ebp
sete %al
movl %r14d, %edx
notb %dl
movb $0x1, %cl
testb %al, %dl
jne 0x8f63d
testl %ebp, %ebp
sete 0x3(%rsp)
movq %rbx, %rdi
movl $0x20, %esi
callq 0xeba56
movq %rax, %r13
leaq 0x10(%rsp), %rsi
movl $0x7c, %edx
movq %rax, %rdi
callq 0xebe72
movq %r13, %rdi
callq 0xebe2a
movl %eax, %r12d
movq %r13, %rdi
callq 0xebe1d
cmpl %ebp, %r12d
sete %al
movl %r14d, %ecx
xorb $0x1, %cl
orb 0x3(%rsp), %cl
orb %al, %cl
movl 0x4(%rsp), %eax
andb %r14b, %al
cmpb $0x1, %al
jne 0x8f65e
testl %r15d, %r15d
je 0x8f65e
testb %cl, %cl
movl $0x5a, %ecx
movl $0x13, %eax
cmovnel %ecx, %eax
jmp 0x8f688
xorl %ebp, %ebp
movl $0x0, %eax
testb %cl, %cl
je 0x8f538
testl %r15d, %r15d
movl $0x1d, %eax
movl $0x13, %ecx
cmovnel %eax, %ecx
testb %r14b, %r14b
movl $0x31, %eax
cmovel %ecx, %eax
movb $0x1, %bpl
jmp 0x8f538