// File: /workspace/github_c_makefile_star2_O2/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
pushq $0xe
popq %r14
cmoveq %r15, %r14
movq %rbp, 0x18(%rsp)
leaq (%r14,%rbp), %rax
cmpq $0x10, %rax
jl 0xec03e
testb $0x1, %r13b
movq 0x10(%rsp), %rbp
je 0xebc7e
testb $0x4, %r13b
je 0xebc58
leaq 0x6(%r12), %rsi
movq %rbp, %rdi
callq 0xe3fa3
movl %eax, 0x4(%rbx)
leaq 0x8(%r12), %rsi
movq %rbp, %rdi
callq 0xe3fa3
movl %eax, 0x8(%rbx)
movl 0x4(%rbx), %edx
leaq 0x36029(%rip), %rsi     # 0x121c73
movq 0x8(%rsp), %rdi
movl %eax, %ecx
xorl %eax, %eax
callq 0xde896
leaq 0xa(%r12), %rsi
movq %rbp, %rdi
callq 0xe409f
movq %rax, 0x10(%rbx)
leaq 0x5129a(%rip), %rsi     # 0x13cf0a
movq 0x8(%rsp), %rdi
movl %eax, %edx
xorl %eax, %eax
callq 0xde896
addq %r14, %r12
movq %rbp, %rdi
movq %r12, %rsi
callq 0xe409f
movq %rax, 0x18(%rbx)
testb $0x2, %r13b
je 0xebcae
cmpq $0x474e5089, %rax       # imm = 0x474E5089
jne 0xebcae
andq $0x0, 0x18(%rbx)
movl $0x1, (%rbx)
jmp 0xec03a
leaq 0x51265(%rip), %rsi     # 0x13cf1a
xorl %r15d, %r15d
movq 0x8(%rsp), %rdi
movl %eax, %edx
xorl %eax, %eax
callq 0xde896
movq 0x18(%rbx), %rax
cmpq $0xc, %rax
jne 0xebdc0
movq $0x3, 0x48(%rbx)
leaq 0x4(%r12), %rsi
movq %rbp, %rdi
callq 0xe3fa3
movq %rax, 0x20(%rbx)
leaq 0x6(%r12), %rsi
movq %rbp, %rdi
callq 0xe3fa3
movq %rax, 0x28(%rbx)
addq $0xa, %r12
movq %rbp, %rdi
movq %r12, %rsi
callq 0xe3fa3
pushq $0x30
popq %rcx
movq %rax, (%rbx,%rcx)
testb $0x2, %r13b
je 0xebd2a
movq 0x28(%rbx), %rax
pushq $0x2
popq %rcx
cqto
idivq %rcx
movq %rax, 0x28(%rbx)
movq 0x30(%rbx), %rdi
leaq -0x1(%rdi), %rcx
movl $0x1000000, %eax        # imm = 0x1000000
cmpq $0x7, %rcx
movq 0x8(%rsp), %r15
ja 0xebd5b
cmpq $0x0, 0x50(%rbx)
jne 0xebd56
callq 0xdfba1
movq %rax, 0x50(%rbx)
movq 0x30(%rbx), %rdi
callq 0xdfba1
movq %rax, 0x58(%rbx)
movq 0x20(%rbx), %rsi
movq 0x28(%rbx), %rdx
movq %r15, %rdi
callq 0xdf038
movl 0x30(%rbx), %edx
leaq 0x4242c(%rip), %rsi     # 0x12e1a5
movq %r15, %rdi
xorl %eax, %eax
callq 0xde896
movl %r13d, %eax
shrb $0x3, %al
movl 0x38(%rbx), %edi
cmpl $0x10000, %edi          # imm = 0x10000
setae %cl
andb %al, %cl
cmpb $0x1, %cl
jne 0xebe9b
leaq 0x30(%rsp), %rcx
leaq 0x414f7(%rip), %rdx     # 0x12d2a3
leaq 0x50(%rsp), %rdi
pushq $0x50
popq %rsi
xorl %eax, %eax
callq 0xde40c
jmp 0xebeaa
addq $-0x10, %rax
cmpq $0x6c, %rax
ja 0xec03e
movq $0x4, 0x48(%rbx)
leaq 0x4(%r12), %rsi
movq 0x10(%rsp), %rbp
movq %rbp, %rdi
callq 0xe409f
movq %rax, 0x20(%rbx)
leaq 0x8(%r12), %rsi
movq %rbp, %rdi
callq 0xe40f2
movq %rax, 0x28(%rbx)
testq %rax, %rax
jns 0xebe13
movl $0x1, 0x9c(%rbx)
negq %rax
movq %rax, 0x28(%rbx)
leaq 0xe(%r12), %rsi
movq %rbp, %rdi
callq 0xe3fa3
movq %rax, 0x30(%rbx)
cmpq $0x14, 0x18(%rbx)
jl 0xebd14
leaq 0x10(%r12), %r15
movq %rbp, %rdi
movq %r15, %rsi
callq 0xe409f
movl %eax, 0x38(%rbx)
testb $0x8, %r13b
je 0xebe5e
leaq 0x20(%rsp), %rdx
pushq $0x4
popq %rcx
movq %rbp, %rdi
movq %r15, %rsi
xorl %r8d, %r8d
callq 0xe657c
cmpq $0x18, 0x18(%rbx)
jl 0xebd14
leaq 0x14(%r12), %rsi
movq %rbp, %rdi
callq 0xe409f
movq %rax, 0x40(%rbx)
cmpq $0x24, 0x18(%rbx)
jl 0xebd14
addq $0x20, %r12
movq %rbp, %rdi
movq %r12, %rsi
callq 0xe409f
pushq $0x50
jmp 0xebd0f
leaq 0x50(%rsp), %rsi
pushq $0x50
popq %rdx
xorl %ecx, %ecx
callq 0xebb30
movl 0x38(%rbx), %edx
leaq 0x4c90e(%rip), %rsi     # 0x1387c2
leaq 0x50(%rsp), %rcx
movq %r15, %rdi
xorl %eax, %eax
callq 0xde896
movq 0x40(%rbx), %rdx
testq %rdx, %rdx
je 0xebedd
leaq 0x5105c(%rip), %rsi     # 0x13cf2f
movq %r15, %rdi
xorl %eax, %eax
callq 0xde896
movl 0x50(%rbx), %edx
leaq 0x2016f(%rip), %rsi     # 0x10c056
movq %r15, %rdi
xorl %eax, %eax
callq 0xde896
movq 0x50(%rbx), %rdx
cmpq $0x101, %rdx            # imm = 0x101
jl 0xebf1d
cmpq $0x9, 0x30(%rbx)
jl 0xebf1d
leaq 0x51031(%rip), %rsi     # 0x13cf3d
movq %r15, %rdi
xorl %eax, %eax
callq 0xdf05a
andq $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 0xebf5d
cmpl $0x3, %eax
jne 0xebf5a
addq $0xc, %rdx
movq %rdx, 0x88(%rbx)
xorl %eax, %eax
cmpq $0x2, 0x30(%rbx)
setl %al
jmp 0xebf5d
pushq $0x1
popq %rax
movl %eax, 0x98(%rbx)
movq 0x20(%rbx), %rsi
movq 0x28(%rbx), %rdx
movq %r15, %rdi
testb $0x10, %r13b
jne 0xebf7b
callq 0xe6be1
jmp 0xebf80
callq 0xe6bb4
testl %eax, %eax
je 0xebf9b
cmpl $0x0, 0x38(%rbx)
je 0xebfa3
movq 0x18(%rsp), %rax
movq %rax, 0x90(%rbx)
jmp 0xec03a
xorl %r15d, %r15d
jmp 0xec03e
movq 0x20(%rbx), %rax
imulq 0x30(%rbx), %rax
addq $0x1f, %rax
pushq $0x20
popq %r14
cqto
idivq %r14
leaq (,%rax,4), %rdx
movq %rdx, 0x60(%rbx)
imulq 0x28(%rbx), %rdx
movq %rdx, 0x68(%rbx)
leaq 0x50f8f(%rip), %rsi     # 0x13cf64
movq %r15, %rdi
xorl %eax, %eax
callq 0xde896
testb $0x2, %r13b
jne 0xebfee
andq $0x0, 0x78(%rbx)
xorl %eax, %eax
jmp 0xec025
movq 0x20(%rbx), %rax
addq $0x1f, %rax
cqto
idivq %r14
leaq (,%rax,4), %rdx
movq %rdx, 0x70(%rbx)
imulq 0x28(%rbx), %rdx
movq %rdx, 0x78(%rbx)
leaq 0x50f61(%rip), %rsi     # 0x13cf78
movq %r15, %rdi
xorl %eax, %eax
callq 0xde896
movq 0x78(%rbx), %rax
movq 0x68(%rbx), %rcx
addq 0x88(%rbx), %rcx
addq %rax, %rcx
movq %rcx, 0x90(%rbx)
pushq $0x1
popq %r15
movl %r15d, %eax
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq