// File: /workspace/github_c_makefile_star2_O3/jsummers[P]deark/src/fmtutil.c
// Function: fmtutil_get_bmpinfo
int fmtutil_get_bmpinfo(deark *c, dbuf *f, struct de_bmpinfo *bi, i64 pos,
	i64 len, unsigned int flags)
{
	i64 fhs; // file header size
	i64 bmih_pos;
	struct de_fourcc cmpr4cc;
	char cmprname_dbgstr[80];

	de_zeromem(bi, sizeof(struct de_bmpinfo));
	de_zeromem(&cmpr4cc, sizeof(struct de_fourcc));

	fhs = (flags & DE_BMPINFO_HAS_FILEHEADER) ? 14 : 0;

	if(fhs+len < 16) return 0;

	if(fhs) {
		if(flags & DE_BMPINFO_HAS_HOTSPOT) {
			bi->hotspot_x = (int)dbuf_getu16le(f, pos+6);
			bi->hotspot_y = (int)dbuf_getu16le(f, pos+8);
			de_dbg(c, "hotspot: (%d,%d)", bi->hotspot_x, bi->hotspot_y);
		}

		bi->bitsoffset = dbuf_getu32le(f, pos+10);
		de_dbg(c, "bits offset: %d", (int)bi->bitsoffset);
	}

	bmih_pos = pos + fhs;

	bi->infohdrsize = dbuf_getu32le(f, bmih_pos);

	if(bi->infohdrsize==0x474e5089 && (flags & DE_BMPINFO_ICO_FORMAT)) {
		// We don't examine PNG-formatted icons, but we can identify them.
		bi->infohdrsize = 0;
		bi->file_format = DE_BMPINFO_FMT_PNG;
		return 1;
	}

	de_dbg(c, "info header size: %d", (int)bi->infohdrsize);

	if(bi->infohdrsize==12) {
		bi->bytes_per_pal_entry = 3;
		bi->width = dbuf_getu16le(f, bmih_pos+4);
		bi->height = dbuf_getu16le(f, bmih_pos+6);
		bi->bitcount = dbuf_getu16le(f, bmih_pos+10);
	}
	else if(bi->infohdrsize>=16 && bi->infohdrsize<=124) {
		bi->bytes_per_pal_entry = 4;
		bi->width = dbuf_getu32le(f, bmih_pos+4);
		bi->height = dbuf_geti32le(f, bmih_pos+8);
		if(bi->height<0) {
			bi->is_topdown = 1;
			bi->height = -bi->height;
		}
		bi->bitcount = dbuf_getu16le(f, bmih_pos+14);
		if(bi->infohdrsize>=20) {
			bi->compression_field = (u32)dbuf_getu32le(f, bmih_pos+16);
			if(flags & DE_BMPINFO_CMPR_IS_4CC) {
				dbuf_read_fourcc(f, bmih_pos+16, &cmpr4cc, 4, 0x0);
			}
		}
		if(bi->infohdrsize>=24) {
			bi->sizeImage_field = dbuf_getu32le(f, bmih_pos+20);
		}
		if(bi->infohdrsize>=36) {
			bi->pal_entries = dbuf_getu32le(f, bmih_pos+32);
		}
	}
	else {
		return 0;
	}

	if(flags & DE_BMPINFO_ICO_FORMAT) bi->height /= 2;

	if(bi->bitcount>=1 && bi->bitcount<=8) {
		if(bi->pal_entries==0) {
			bi->pal_entries = de_pow2(bi->bitcount);
		}
		// I think the NumColors field (in icons) is supposed to be the maximum number of
		// colors implied by the bit depth, not the number of colors in the palette.
		bi->num_colors = de_pow2(bi->bitcount);
	}
	else {
		// An arbitrary value. All that matters is that it's >=256.
		bi->num_colors = 16777216;
	}

	de_dbg_dimensions(c, bi->width, bi->height);
	de_dbg(c, "bit count: %d", (int)bi->bitcount);

	if((flags & DE_BMPINFO_CMPR_IS_4CC) && (bi->compression_field>0xffff)) {
		de_snprintf(cmprname_dbgstr, sizeof(cmprname_dbgstr), "'%s'", cmpr4cc.id_dbgstr);
	}
	else {
		fmtutil_get_bmp_compression_name(bi->compression_field,
			cmprname_dbgstr, sizeof(cmprname_dbgstr), 0);
	}
	de_dbg(c, "compression: %u (%s)", (unsigned int)bi->compression_field, cmprname_dbgstr);

	if(bi->sizeImage_field!=0) {
		de_dbg(c, "sizeImage: %u", (unsigned int)bi->sizeImage_field);
	}

	de_dbg(c, "palette entries: %u", (unsigned int)bi->pal_entries);
	if(bi->pal_entries>256 && bi->bitcount>8) {
		de_warn(c, "Ignoring bad palette size (%u entries)", (unsigned int)bi->pal_entries);
		bi->pal_entries = 0;
	}

	bi->pal_bytes = bi->bytes_per_pal_entry*bi->pal_entries;
	bi->size_of_headers_and_pal = fhs + bi->infohdrsize + bi->pal_bytes;

	// FIXME: cmpr type 3 doesn't always mean BITFIELDS
	if(bi->compression_field==3) {
		bi->size_of_headers_and_pal += 12; // BITFIELDS
	}

	bi->is_compressed = !((bi->compression_field==0) ||
		(bi->compression_field==3 && bi->bitcount>1));

	if(flags & DE_BMPINFO_NOERR) {
		if(!de_good_image_dimensions_noerr(c, bi->width, bi->height)) {
			return 0;
		}
	}
	else {
		if(!de_good_image_dimensions(c, bi->width, bi->height)) {
			return 0;
		}
	}

	// TODO: This needs work, to decide how to handle compressed images.
	// TODO: What about BI_BITFIELDS images?
	if(bi->compression_field==0) {
		// Try to figure out the true size of the resource, minus any padding.

		bi->rowspan = ((bi->bitcount*bi->width +31)/32)*4;
		bi->foreground_size = bi->rowspan * bi->height;
		de_dbg(c, "foreground size: %d", (int)bi->foreground_size);

		if(flags & DE_BMPINFO_ICO_FORMAT) {
			bi->mask_rowspan = ((bi->width +31)/32)*4;
			bi->mask_size = bi->mask_rowspan * bi->height;
			de_dbg(c, "mask size: %d", (int)bi->mask_size);
		}
		else {
			bi->mask_size = 0;
		}

		bi->total_size = bi->size_of_headers_and_pal + bi->foreground_size + bi->mask_size;
	}
	else {
		// Don't try to figure out the true size of compressed or other unusual images.
		bi->total_size = len;
	}

	return 1;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xa8, %rsp
movl %r9d, %r13d
movq %r8, %rbp
movq %rcx, %r12
movq %rdx, %rbx
movq %rsi, 0x10(%rsp)
movq %rdi, 0x8(%rsp)
xorl %r15d, %r15d
movl $0xa0, %edx
movq %rbx, %rdi
xorl %esi, %esi
callq 0x18140
xorps %xmm0, %xmm0
movaps %xmm0, 0x20(%rsp)
movaps %xmm0, 0x30(%rsp)
movaps %xmm0, 0x40(%rsp)
testb $0x1, %r13b
movl $0xe, %r14d
cmoveq %r15, %r14
movq %rbp, 0x18(%rsp)
leaq (%r14,%rbp), %rax
cmpq $0x10, %rax
jl 0xf78e5
testb $0x1, %r13b
movq 0x10(%rsp), %rbp
je 0xf7500
testb $0x4, %r13b
je 0xf74da
leaq 0x6(%r12), %rsi
movq %rbp, %rdi
callq 0xeebc8
movl %eax, 0x4(%rbx)
leaq 0x8(%r12), %rsi
movq %rbp, %rdi
callq 0xeebc8
movl %eax, 0x8(%rbx)
movl 0x4(%rbx), %edx
leaq 0x37a2f(%rip), %rsi     # 0x12eefb
movq 0x8(%rsp), %rdi
movl %eax, %ecx
xorl %eax, %eax
callq 0xe8617
leaq 0xa(%r12), %rsi
movq %rbp, %rdi
callq 0xeed61
movq %rax, 0x10(%rbx)
leaq 0x52ee8(%rip), %rsi     # 0x14a3da
movq 0x8(%rsp), %rdi
movl %eax, %edx
xorl %eax, %eax
callq 0xe8617
addq %r14, %r12
movq %rbp, %rdi
movq %r12, %rsi
callq 0xeed61
movq %rax, 0x18(%rbx)
testb $0x2, %r13b
je 0xf7533
cmpq $0x474e5089, %rax       # imm = 0x474E5089
jne 0xf7533
movq $0x0, 0x18(%rbx)
movl $0x1, (%rbx)
jmp 0xf78df
leaq 0x52eb0(%rip), %rsi     # 0x14a3ea
xorl %r15d, %r15d
movq 0x8(%rsp), %rdi
movl %eax, %edx
xorl %eax, %eax
callq 0xe8617
movq 0x18(%rbx), %rax
cmpq $0xc, %rax
jne 0xf764e
movq $0x3, 0x48(%rbx)
leaq 0x4(%r12), %rsi
movq %rbp, %rdi
callq 0xeebc8
movq %rax, 0x20(%rbx)
leaq 0x6(%r12), %rsi
movq %rbp, %rdi
callq 0xeebc8
movq %rax, 0x28(%rbx)
addq $0xa, %r12
movq %rbp, %rdi
movq %r12, %rsi
callq 0xeebc8
movl $0x30, %ecx
movq %rax, (%rbx,%rcx)
testb $0x2, %r13b
je 0xf75b6
movq 0x28(%rbx), %rax
movq %rax, %rcx
shrq $0x3f, %rcx
addq %rax, %rcx
sarq %rcx
movq %rcx, 0x28(%rbx)
movq 0x30(%rbx), %rdi
leaq -0x1(%rdi), %rcx
movl $0x1000000, %eax        # imm = 0x1000000
cmpq $0x7, %rcx
movq 0x8(%rsp), %r15
ja 0xf75e7
cmpq $0x0, 0x50(%rbx)
jne 0xf75e2
callq 0xe9c9b
movq %rax, 0x50(%rbx)
movq 0x30(%rbx), %rdi
callq 0xe9c9b
movq %rax, 0x58(%rbx)
movq 0x20(%rbx), %rsi
movq 0x28(%rbx), %rdx
movq %r15, %rdi
callq 0xe8f88
movl 0x30(%rbx), %edx
leaq 0x43e90(%rip), %rsi     # 0x13b495
movq %r15, %rdi
xorl %eax, %eax
callq 0xe8617
movl %r13d, %eax
shrb $0x3, %al
movl 0x38(%rbx), %edi
cmpl $0x10000, %edi          # imm = 0x10000
setae %cl
andb %al, %cl
cmpb $0x1, %cl
jne 0xf772e
leaq 0x30(%rsp), %rcx
leaq 0x42f5f(%rip), %rdx     # 0x13a597
leaq 0x50(%rsp), %rdi
movl $0x50, %esi
xorl %eax, %eax
callq 0xe8193
jmp 0xf773f
addq $-0x10, %rax
cmpq $0x6c, %rax
ja 0xf78e5
movq $0x4, 0x48(%rbx)
leaq 0x4(%r12), %rsi
movq 0x10(%rsp), %rbp
movq %rbp, %rdi
callq 0xeed61
movq %rax, 0x20(%rbx)
leaq 0x8(%r12), %rsi
movq %rbp, %rdi
callq 0xeedfa
movq %rax, 0x28(%rbx)
testq %rax, %rax
jns 0xf76a1
movl $0x1, 0x9c(%rbx)
negq %rax
movq %rax, 0x28(%rbx)
leaq 0xe(%r12), %rsi
movq %rbp, %rdi
callq 0xeebc8
movq %rax, 0x30(%rbx)
cmpq $0x14, 0x18(%rbx)
jl 0xf759b
leaq 0x10(%r12), %r15
movq %rbp, %rdi
movq %r15, %rsi
callq 0xeed61
movl %eax, 0x38(%rbx)
testb $0x8, %r13b
je 0xf76ee
leaq 0x20(%rsp), %rdx
movq %rbp, %rdi
movq %r15, %rsi
movl $0x4, %ecx
xorl %r8d, %r8d
callq 0xf1762
cmpq $0x18, 0x18(%rbx)
jl 0xf759b
leaq 0x14(%r12), %rsi
movq %rbp, %rdi
callq 0xeed61
movq %rax, 0x40(%rbx)
cmpq $0x24, 0x18(%rbx)
jl 0xf759b
addq $0x20, %r12
movq %rbp, %rdi
movq %r12, %rsi
callq 0xeed61
movl $0x50, %ecx
jmp 0xf7597
leaq 0x50(%rsp), %rsi
movl $0x50, %edx
xorl %ecx, %ecx
callq 0xf73b0
movl 0x38(%rbx), %edx
leaq 0x4e4c9(%rip), %rsi     # 0x145c12
leaq 0x50(%rsp), %rcx
movq %r15, %rdi
xorl %eax, %eax
callq 0xe8617
movq 0x40(%rbx), %rdx
testq %rdx, %rdx
je 0xf7772
leaq 0x52c97(%rip), %rsi     # 0x14a3ff
movq %r15, %rdi
xorl %eax, %eax
callq 0xe8617
movl 0x50(%rbx), %edx
leaq 0x219ca(%rip), %rsi     # 0x119146
movq %r15, %rdi
xorl %eax, %eax
callq 0xe8617
movq 0x50(%rbx), %rdx
cmpq $0x101, %rdx            # imm = 0x101
jl 0xf77b5
cmpq $0x9, 0x30(%rbx)
jl 0xf77b5
leaq 0x52c6c(%rip), %rsi     # 0x14a40d
movq %r15, %rdi
xorl %eax, %eax
callq 0xe8faa
movq $0x0, 0x50(%rbx)
xorl %edx, %edx
imulq 0x48(%rbx), %rdx
movq %rdx, 0x80(%rbx)
addq %r14, %rdx
addq 0x18(%rbx), %rdx
movq %rdx, 0x88(%rbx)
movl 0x38(%rbx), %eax
testl %eax, %eax
je 0xf77f7
cmpl $0x3, %eax
jne 0xf77f2
addq $0xc, %rdx
movq %rdx, 0x88(%rbx)
xorl %eax, %eax
cmpq $0x2, 0x30(%rbx)
setl %al
jmp 0xf77f7
movl $0x1, %eax
movl %eax, 0x98(%rbx)
movq 0x20(%rbx), %rsi
movq 0x28(%rbx), %rdx
movq %r15, %rdi
testb $0x10, %r13b
jne 0xf7815
callq 0xf1db1
jmp 0xf781a
callq 0xf1d84
testl %eax, %eax
je 0xf7835
cmpl $0x0, 0x38(%rbx)
je 0xf783d
movq 0x18(%rsp), %rax
movq %rax, 0x90(%rbx)
jmp 0xf78df
xorl %r15d, %r15d
jmp 0xf78e5
movq 0x20(%rbx), %rdx
imulq 0x30(%rbx), %rdx
leaq 0x1f(%rdx), %rax
addq $0x3e, %rdx
testq %rax, %rax
cmovnsq %rax, %rdx
sarq $0x5, %rdx
shlq $0x2, %rdx
movq %rdx, 0x60(%rbx)
imulq 0x28(%rbx), %rdx
movq %rdx, 0x68(%rbx)
leaq 0x52bc3(%rip), %rsi     # 0x14a434
movq %r15, %rdi
xorl %eax, %eax
callq 0xe8617
testb $0x2, %r13b
jne 0xf788d
movq $0x0, 0x78(%rbx)
xorl %eax, %eax
jmp 0xf78ca
movq 0x20(%rbx), %rdx
leaq 0x1f(%rdx), %rax
addq $0x3e, %rdx
testq %rax, %rax
cmovnsq %rax, %rdx
sarq $0x5, %rdx
shlq $0x2, %rdx
movq %rdx, 0x70(%rbx)
imulq 0x28(%rbx), %rdx
movq %rdx, 0x78(%rbx)
leaq 0x52b8c(%rip), %rsi     # 0x14a448
movq %r15, %rdi
xorl %eax, %eax
callq 0xe8617
movq 0x78(%rbx), %rax
movq 0x68(%rbx), %rcx
addq 0x88(%rbx), %rcx
addq %rax, %rcx
movq %rcx, 0x90(%rbx)
movl $0x1, %r15d
movl %r15d, %eax
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq