// File: /workspace/github_c_makefile_star2_O0/jsummers[P]deark/modules/makichan.c
// Function: do_mag_decompress
static int do_mag_decompress(deark *c, lctx *d)
{
	static const u8 delta_x[16] = { 0,1,2,4,0,1,0,1,2,0,1,2,0,1,2, 0 };
	static const u8 delta_y[16] = { 0,0,0,0,1,1,2,2,2,4,4,4,8,8,8,16 };
	i64 x, y;
	i64 a_pos, b_pos;
	i64 p_pos;
	int a_bitnum; // Index of next bit to read. -1 = no more bits in a_byte.
	u8 a_byte = 0x00;
	u8 b_byte;
	int k;
	i64 dpos;
	u8 *action_byte_buf = NULL;
	u8 wordbuf[2];

	de_dbg(c, "decompressing pixels");

	// Presumably, due to the compression scheme, every row must have a
	// multiple of 4 bytes.
	d->rowspan = ((d->width * d->bits_per_pixel + 31)/32)*4;

	d->unc_pixels = dbuf_create_membuf(c, d->rowspan * d->height, 1);

	a_pos = d->flag_a_offset;
	a_bitnum = -1;
	b_pos = d->flag_b_offset;
	p_pos = d->pixels_offset;

	action_byte_buf = de_malloc(c, d->rowspan/4);

	for(y=0; y<d->height; y++) {
		for(x=0; x<d->rowspan/4; x++) {
			u8 action_byte;
			u8 flag_a_bit;

			// Read next flag A bit
			if(a_bitnum<0) {
				a_byte = de_getbyte(a_pos++);
				a_bitnum = 7;
			}
			flag_a_bit = a_byte & (1 << a_bitnum--);

			if(flag_a_bit) {
				// If flag_a_bit is unset, re-use the action byte from the
				// previous row.
				// If flag bit A is set, the new action byte is the one from the
				// previous row XORed with the next B byte (don't ask me why).
				b_byte = de_getbyte(b_pos++);
				action_byte_buf[x] ^= b_byte;
			}

			action_byte = action_byte_buf[x];

			// Produce 4 uncompressed bytes, 2 for each nibble in the
			// action byte.
			for(k=0; k<2; k++) {
				unsigned int dcode;

				if(k==0)
					dcode = (unsigned int)((action_byte&0xf0)>>4);
				else
					dcode = (unsigned int)(action_byte&0x0f);

				if(dcode==0) {
					// An "uncompressed" data word. Read it from the source file.
					de_read(wordbuf, p_pos, 2);
					p_pos += 2;
				}
				else {
					// Copy the data word from an earlier location in the image.
					dpos = d->unc_pixels->len -
						d->rowspan*(i64)delta_y[dcode] -
						2*(i64)delta_x[dcode];
					dbuf_read(d->unc_pixels, wordbuf, dpos, 2);
				}
				dbuf_write(d->unc_pixels, wordbuf, 2);
			}
		}
	}

	de_free(c, action_byte_buf);
	return 1;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movb $0x0, -0x3d(%rbp)
movq $0x0, -0x58(%rbp)
movq -0x8(%rbp), %rdi
leaq 0xe086f(%rip), %rsi     # 0x1bbbc6
movb $0x0, %al
callq 0x15b0d0
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq -0x10(%rbp), %rcx
imulq 0x50(%rcx), %rax
addq $0x1f, %rax
movl $0x20, %ecx
cqto
idivq %rcx
movq %rax, %rcx
shlq $0x2, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x58(%rax)
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rsi
movq -0x10(%rbp), %rax
imulq 0x10(%rax), %rsi
movl $0x1, %edx
callq 0x168020
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x88(%rax)
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x28(%rbp)
movl $0xffffffff, -0x3c(%rbp) # imm = 0xFFFFFFFF
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rax
movq %rax, -0x38(%rbp)
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rax
movl $0x4, %ecx
cqto
idivq %rcx
movq %rax, %rsi
callq 0x15b780
movq %rax, -0x58(%rbp)
movq $0x0, -0x20(%rbp)
movq -0x20(%rbp), %rax
movq -0x10(%rbp), %rcx
cmpq 0x10(%rcx), %rax
jge 0xdb5f5
movq $0x0, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x68(%rbp)
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rax
movl $0x4, %ecx
cqto
idivq %rcx
movq %rax, %rcx
movq -0x68(%rbp), %rax
cmpq %rcx, %rax
jge 0xdb5e2
cmpl $0x0, -0x3c(%rbp)
jge 0xdb47e
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rdi
movq -0x28(%rbp), %rsi
movq %rsi, %rax
addq $0x1, %rax
movq %rax, -0x28(%rbp)
callq 0x165060
movb %al, -0x3d(%rbp)
movl $0x7, -0x3c(%rbp)
movzbl -0x3d(%rbp), %eax
movl -0x3c(%rbp), %ecx
movl %ecx, %edx
addl $-0x1, %edx
movl %edx, -0x3c(%rbp)
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
andl %ecx, %eax
movb %al, -0x5c(%rbp)
cmpb $0x0, -0x5c(%rbp)
je 0xdb4d5
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rdi
movq -0x30(%rbp), %rsi
movq %rsi, %rax
addq $0x1, %rax
movq %rax, -0x30(%rbp)
callq 0x165060
movb %al, -0x3e(%rbp)
movzbl -0x3e(%rbp), %esi
movq -0x58(%rbp), %rax
movq -0x18(%rbp), %rcx
movzbl (%rax,%rcx), %edx
xorl %esi, %edx
movb %dl, (%rax,%rcx)
movq -0x58(%rbp), %rax
movq -0x18(%rbp), %rcx
movb (%rax,%rcx), %al
movb %al, -0x5b(%rbp)
movl $0x0, -0x44(%rbp)
cmpl $0x2, -0x44(%rbp)
jge 0xdb5cf
cmpl $0x0, -0x44(%rbp)
jne 0xdb50b
movzbl -0x5b(%rbp), %eax
andl $0xf0, %eax
sarl $0x4, %eax
movl %eax, -0x60(%rbp)
jmp 0xdb515
movzbl -0x5b(%rbp), %eax
andl $0xf, %eax
movl %eax, -0x60(%rbp)
cmpl $0x0, -0x60(%rbp)
jne 0xdb543
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rdi
leaq -0x5a(%rbp), %rsi
movq -0x38(%rbp), %rdx
movl $0x2, %ecx
callq 0x164d10
movq -0x38(%rbp), %rax
addq $0x2, %rax
movq %rax, -0x38(%rbp)
jmp 0xdb5a8
movq -0x10(%rbp), %rax
movq 0x88(%rax), %rax
movq 0x18(%rax), %rax
movq -0x10(%rbp), %rcx
movq 0x58(%rcx), %rcx
movl -0x60(%rbp), %edx
movl %edx, %esi
leaq 0xe06ca(%rip), %rdx     # 0x1bbc30
movzbl (%rdx,%rsi), %edx
imulq %rdx, %rcx
subq %rcx, %rax
movl -0x60(%rbp), %ecx
movl %ecx, %edx
leaq 0xe06a3(%rip), %rcx     # 0x1bbc20
movzbl (%rcx,%rdx), %ecx
shlq %rcx
subq %rcx, %rax
movq %rax, -0x50(%rbp)
movq -0x10(%rbp), %rax
movq 0x88(%rax), %rdi
leaq -0x5a(%rbp), %rsi
movq -0x50(%rbp), %rdx
movl $0x2, %ecx
callq 0x164d10
movq -0x10(%rbp), %rax
movq 0x88(%rax), %rdi
leaq -0x5a(%rbp), %rsi
movl $0x2, %edx
callq 0x166170
movl -0x44(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x44(%rbp)
jmp 0xdb4ea
jmp 0xdb5d1
movq -0x18(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x18(%rbp)
jmp 0xdb428
jmp 0xdb5e4
movq -0x20(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x20(%rbp)
jmp 0xdb40e
movq -0x8(%rbp), %rdi
movq -0x58(%rbp), %rsi
callq 0x15b820
movl $0x1, %eax
addq $0x70, %rsp
popq %rbp
retq
nopl (%rax)