// File: /workspace/github_c_makefile_star2_O1/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 0xf7d2c
testb $0x1, %r13b
movq 0x10(%rsp), %rbp
je 0xf795c
testb $0x4, %r13b
je 0xf7936
leaq 0x6(%r12), %rsi
movq %rbp, %rdi
callq 0xef1ca
movl %eax, 0x4(%rbx)
leaq 0x8(%r12), %rsi
movq %rbp, %rdi
callq 0xef1ca
movl %eax, 0x8(%rbx)
movl 0x4(%rbx), %edx
leaq 0x372c3(%rip), %rsi     # 0x12ebeb
movq 0x8(%rsp), %rdi
movl %eax, %ecx
xorl %eax, %eax
callq 0xe9226
leaq 0xa(%r12), %rsi
movq %rbp, %rdi
callq 0xef37e
movq %rax, 0x10(%rbx)
leaq 0x524dc(%rip), %rsi     # 0x149e2a
movq 0x8(%rsp), %rdi
movl %eax, %edx
xorl %eax, %eax
callq 0xe9226
addq %r14, %r12
movq %rbp, %rdi
movq %r12, %rsi
callq 0xef37e
movq %rax, 0x18(%rbx)
testb $0x2, %r13b
je 0xf798f
cmpq $0x474e5089, %rax       # imm = 0x474E5089
jne 0xf798f
movq $0x0, 0x18(%rbx)
movl $0x1, (%rbx)
jmp 0xf7d26
leaq 0x524a4(%rip), %rsi     # 0x149e3a
xorl %r15d, %r15d
movq 0x8(%rsp), %rdi
movl %eax, %edx
xorl %eax, %eax
callq 0xe9226
movq 0x18(%rbx), %rax
cmpq $0xc, %rax
jne 0xf7b6d
movq $0x3, 0x48(%rbx)
leaq 0x4(%r12), %rsi
movq %rbp, %rdi
callq 0xef1ca
movq %rax, 0x20(%rbx)
leaq 0x6(%r12), %rsi
movq %rbp, %rdi
callq 0xef1ca
movq %rax, 0x28(%rbx)
addq $0xa, %r12
movq %rbp, %rdi
movq %r12, %rsi
callq 0xef1ca
movl $0x30, %ecx
movq %rax, (%rbx,%rcx)
testb $0x2, %r13b
je 0xf7a12
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 0xf7a43
cmpq $0x0, 0x50(%rbx)
jne 0xf7a3a
callq 0xea7f2
movq %rax, 0x50(%rbx)
movq 0x30(%rbx), %rdi
callq 0xea7f2
movq %rax, 0x58(%rbx)
movq 0x20(%rbx), %rsi
movq 0x28(%rbx), %rdx
movq %r15, %rdi
callq 0xe9b05
movl 0x30(%rbx), %edx
leaq 0x4367c(%rip), %rsi     # 0x13b0dd
movq %r15, %rdi
xorl %eax, %eax
callq 0xe9226
testb $0x8, %r13b
je 0xf7a99
cmpl $0x10000, 0x38(%rbx)    # imm = 0x10000
jb 0xf7a99
leaq 0x30(%rsp), %rcx
leaq 0x4278d(%rip), %rdx     # 0x13a213
leaq 0x50(%rsp), %rdi
movl $0x50, %esi
xorl %eax, %eax
callq 0xe8d67
jmp 0xf7aad
movl 0x38(%rbx), %edi
leaq 0x50(%rsp), %rsi
movl $0x50, %edx
xorl %ecx, %ecx
callq 0xf780c
movl 0x38(%rbx), %edx
leaq 0x4dc7b(%rip), %rsi     # 0x145732
leaq 0x50(%rsp), %rcx
movq %r15, %rdi
xorl %eax, %eax
callq 0xe9226
movq 0x40(%rbx), %rdx
testq %rdx, %rdx
je 0xf7ae0
leaq 0x52379(%rip), %rsi     # 0x149e4f
movq %r15, %rdi
xorl %eax, %eax
callq 0xe9226
movl 0x50(%rbx), %edx
leaq 0x2153c(%rip), %rsi     # 0x119026
movq %r15, %rdi
xorl %eax, %eax
callq 0xe9226
movq 0x50(%rbx), %rdx
cmpq $0x101, %rdx            # imm = 0x101
jl 0xf7b21
cmpq $0x9, 0x30(%rbx)
jl 0xf7b21
leaq 0x5234e(%rip), %rsi     # 0x149e5d
movq %r15, %rdi
xorl %eax, %eax
callq 0xe9b27
movq $0x0, 0x50(%rbx)
movq 0x50(%rbx), %rax
imulq 0x48(%rbx), %rax
movq %rax, 0x80(%rbx)
addq %r14, %rax
addq 0x18(%rbx), %rax
movq %rax, 0x88(%rbx)
movl 0x38(%rbx), %ecx
testl %ecx, %ecx
je 0xf7c4a
cmpl $0x3, %ecx
jne 0xf7c45
addq $0xc, %rax
movq %rax, 0x88(%rbx)
xorl %ecx, %ecx
cmpq $0x2, 0x30(%rbx)
setl %cl
jmp 0xf7c4a
addq $-0x10, %rax
cmpq $0x6c, %rax
ja 0xf7d2c
movq $0x4, 0x48(%rbx)
leaq 0x4(%r12), %rsi
movq 0x10(%rsp), %rbp
movq %rbp, %rdi
callq 0xef37e
movq %rax, 0x20(%rbx)
leaq 0x8(%r12), %rsi
movq %rbp, %rdi
callq 0xef417
movq %rax, 0x28(%rbx)
testq %rax, %rax
jns 0xf7bc0
movl $0x1, 0x9c(%rbx)
negq %rax
movq %rax, 0x28(%rbx)
leaq 0xe(%r12), %rsi
movq %rbp, %rdi
callq 0xef1ca
movq %rax, 0x30(%rbx)
cmpq $0x14, 0x18(%rbx)
jl 0xf7c09
leaq 0x10(%r12), %r15
movq %rbp, %rdi
movq %r15, %rsi
callq 0xef37e
movl %eax, 0x38(%rbx)
testb $0x8, %r13b
je 0xf7c09
leaq 0x20(%rsp), %rdx
movq %rbp, %rdi
movq %r15, %rsi
movl $0x4, %ecx
xorl %r8d, %r8d
callq 0xf1d74
cmpq $0x18, 0x18(%rbx)
jl 0xf7c21
leaq 0x14(%r12), %rsi
movq %rbp, %rdi
callq 0xef37e
movq %rax, 0x40(%rbx)
cmpq $0x24, 0x18(%rbx)
jl 0xf79f7
addq $0x20, %r12
movq %rbp, %rdi
movq %r12, %rsi
callq 0xef37e
movl $0x50, %ecx
jmp 0xf79f3
movl $0x1, %ecx
movl %ecx, 0x98(%rbx)
movq 0x20(%rbx), %rsi
movq 0x28(%rbx), %rdx
movq %r15, %rdi
testb $0x10, %r13b
jne 0xf7c68
callq 0xf241d
jmp 0xf7c6d
callq 0xf23f0
testl %eax, %eax
je 0xf7c81
cmpl $0x0, 0x38(%rbx)
je 0xf7c89
movq 0x18(%rsp), %rax
jmp 0xf7d1f
xorl %r15d, %r15d
jmp 0xf7d2c
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 0x521c7(%rip), %rsi     # 0x149e84
movq %r15, %rdi
xorl %eax, %eax
callq 0xe9226
testb $0x2, %r13b
jne 0xf7cd7
movq $0x0, 0x78(%rbx)
jmp 0xf7d10
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 0x52192(%rip), %rsi     # 0x149e98
movq %r15, %rdi
xorl %eax, %eax
callq 0xe9226
movq 0x68(%rbx), %rax
addq 0x88(%rbx), %rax
addq 0x78(%rbx), %rax
movq %rax, 0x90(%rbx)
movl $0x1, %r15d
movl %r15d, %eax
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq