// File: OpenFodder[P]SOS_Unpacker/capsimg/Codec/CTRawCodecDecompressor.cpp
// Function: CCTRawCodec::DecompressDensity(unsigned char*, int, unsigned int*)
PUDWORD CCTRawCodec::DecompressDensity(PUBYTE src, int slen, PUDWORD dst)
{
	CapsPack cpk;

	// get density header
	PCAPSPACK pk = GetPackHeader(&cpk, src, slen);
	if (!pk)
		return NULL;

	// use caller supplied buffer or allocate a new one
	PUDWORD buf = dst;
	if (!buf && pk->usize)
		buf = new UDWORD[pk->usize >> 2];

	// buffer pointer to end of destionation and source buffer
	PUDWORD mem = buf + (pk->usize >> 2);
	src += slen;

	// decode the data, see compressor for encoding
	while (mem > buf) {
		int size, ofs;
		UBYTE cb0 = *--src;

		switch (cb0 & 0x03) {
			// data block
			case 0x0:
				// 12 or 4 bit size
				if (cb0 & 0x08)
					size = ((cb0 << 4) & 0xf00) | (*--src);
				else
					size = (cb0 >> 4) + 1;
				if (cb0 & 0x04) {
					// 4 bytes per value
					while (size--) {
						UDWORD data;
						data = (*--src);
						data = (data << 8) | (*--src);
						data = (data << 8) | (*--src);
						data = (data << 8) | (*--src);
						*--mem = data;
					}
				} else {
					// 1 byte per value
					while (size--)
						*--mem = *--src;
				}
				continue;

			// copy block, 8 bit offset, 6 bit size
			case 0x1:
				size = (cb0 >> 2) + 1;
				ofs = (*--src) + 1;
				break;

			// copy block, 16 bit offset, 6 bit size
			case 0x2:
				size = (cb0 >> 2) + 1;
				ofs = (*--src);
				ofs = (ofs << 8) | (*--src);
				break;

				// copy block, 16 bit offset, 14 bit size
			case 0x3:
				size = ((cb0 << 6) & 0x3f00) | (*--src);
				ofs = (*--src);
				ofs = (ofs << 8) | (*--src);
				break;
		}

		// copy decoded data
		while (size--) {
			mem--;
			*mem = mem[ofs];
		}
	}

	return buf;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movq %rdx, -0x20(%rbp)
movq -0x10(%rbp), %rsi
movl -0x14(%rbp), %edx
leaq -0x38(%rbp), %rdi
callq 0x5f80
movq %rax, -0x40(%rbp)
cmpq $0x0, -0x40(%rbp)
jne 0x63fb
movq $0x0, -0x8(%rbp)
jmp 0x66f2
movq -0x20(%rbp), %rax
movq %rax, -0x48(%rbp)
cmpq $0x0, -0x48(%rbp)
jne 0x6445
movq -0x40(%rbp), %rax
cmpl $0x0, 0x4(%rax)
je 0x6445
movq -0x40(%rbp), %rax
movl 0x4(%rax), %eax
shrl $0x2, %eax
movl %eax, %eax
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x4040
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
movq -0x40(%rbp), %rcx
movl 0x4(%rcx), %ecx
shrl $0x2, %ecx
movl %ecx, %ecx
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, -0x50(%rbp)
movl -0x14(%rbp), %ecx
movq -0x10(%rbp), %rax
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0x10(%rbp)
movq -0x50(%rbp), %rax
cmpq -0x48(%rbp), %rax
jbe 0x66ea
movq -0x10(%rbp), %rax
movq %rax, %rcx
decq %rcx
movq %rcx, -0x10(%rbp)
movb -0x1(%rax), %al
movb %al, -0x59(%rbp)
movzbl -0x59(%rbp), %eax
andl $0x3, %eax
movl %eax, %ecx
movq %rcx, -0x68(%rbp)
subl $0x3, %eax
ja 0x66b4
movq -0x68(%rbp), %rax
leaq 0x17b78(%rip), %rcx     # 0x1e02c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movzbl -0x59(%rbp), %eax
andl $0x8, %eax
cmpl $0x0, %eax
je 0x64ef
movzbl -0x59(%rbp), %eax
shll $0x4, %eax
andl $0xf00, %eax            # imm = 0xF00
movq -0x10(%rbp), %rcx
movq %rcx, %rdx
addq $-0x1, %rdx
movq %rdx, -0x10(%rbp)
movzbl -0x1(%rcx), %ecx
orl %ecx, %eax
movl %eax, -0x54(%rbp)
jmp 0x64fc
movzbl -0x59(%rbp), %eax
sarl $0x4, %eax
addl $0x1, %eax
movl %eax, -0x54(%rbp)
movzbl -0x59(%rbp), %eax
andl $0x4, %eax
cmpl $0x0, %eax
je 0x65ae
jmp 0x650e
movl -0x54(%rbp), %eax
movl %eax, %ecx
addl $-0x1, %ecx
movl %ecx, -0x54(%rbp)
cmpl $0x0, %eax
je 0x65ac
movq -0x10(%rbp), %rax
movq %rax, %rcx
addq $-0x1, %rcx
movq %rcx, -0x10(%rbp)
movzbl -0x1(%rax), %eax
movl %eax, -0x60(%rbp)
movl -0x60(%rbp), %eax
shll $0x8, %eax
movq -0x10(%rbp), %rcx
movq %rcx, %rdx
addq $-0x1, %rdx
movq %rdx, -0x10(%rbp)
movzbl -0x1(%rcx), %ecx
orl %ecx, %eax
movl %eax, -0x60(%rbp)
movl -0x60(%rbp), %eax
shll $0x8, %eax
movq -0x10(%rbp), %rcx
movq %rcx, %rdx
addq $-0x1, %rdx
movq %rdx, -0x10(%rbp)
movzbl -0x1(%rcx), %ecx
orl %ecx, %eax
movl %eax, -0x60(%rbp)
movl -0x60(%rbp), %eax
shll $0x8, %eax
movq -0x10(%rbp), %rcx
movq %rcx, %rdx
addq $-0x1, %rdx
movq %rdx, -0x10(%rbp)
movzbl -0x1(%rcx), %ecx
orl %ecx, %eax
movl %eax, -0x60(%rbp)
movl -0x60(%rbp), %ecx
movq -0x50(%rbp), %rax
movq %rax, %rdx
addq $-0x4, %rdx
movq %rdx, -0x50(%rbp)
movl %ecx, -0x4(%rax)
jmp 0x650e
jmp 0x65e9
jmp 0x65b0
movl -0x54(%rbp), %eax
movl %eax, %ecx
addl $-0x1, %ecx
movl %ecx, -0x54(%rbp)
cmpl $0x0, %eax
je 0x65e7
movq -0x10(%rbp), %rax
movq %rax, %rcx
addq $-0x1, %rcx
movq %rcx, -0x10(%rbp)
movzbl -0x1(%rax), %ecx
movq -0x50(%rbp), %rax
movq %rax, %rdx
addq $-0x4, %rdx
movq %rdx, -0x50(%rbp)
movl %ecx, -0x4(%rax)
jmp 0x65b0
jmp 0x65e9
jmp 0x6471
movzbl -0x59(%rbp), %eax
sarl $0x2, %eax
addl $0x1, %eax
movl %eax, -0x54(%rbp)
movq -0x10(%rbp), %rax
movq %rax, %rcx
addq $-0x1, %rcx
movq %rcx, -0x10(%rbp)
movzbl -0x1(%rax), %eax
addl $0x1, %eax
movl %eax, -0x58(%rbp)
jmp 0x66b4
movzbl -0x59(%rbp), %eax
sarl $0x2, %eax
addl $0x1, %eax
movl %eax, -0x54(%rbp)
movq -0x10(%rbp), %rax
movq %rax, %rcx
addq $-0x1, %rcx
movq %rcx, -0x10(%rbp)
movzbl -0x1(%rax), %eax
movl %eax, -0x58(%rbp)
movl -0x58(%rbp), %eax
shll $0x8, %eax
movq -0x10(%rbp), %rcx
movq %rcx, %rdx
addq $-0x1, %rdx
movq %rdx, -0x10(%rbp)
movzbl -0x1(%rcx), %ecx
orl %ecx, %eax
movl %eax, -0x58(%rbp)
jmp 0x66b4
movzbl -0x59(%rbp), %eax
shll $0x6, %eax
andl $0x3f00, %eax           # imm = 0x3F00
movq -0x10(%rbp), %rcx
movq %rcx, %rdx
addq $-0x1, %rdx
movq %rdx, -0x10(%rbp)
movzbl -0x1(%rcx), %ecx
orl %ecx, %eax
movl %eax, -0x54(%rbp)
movq -0x10(%rbp), %rax
movq %rax, %rcx
addq $-0x1, %rcx
movq %rcx, -0x10(%rbp)
movzbl -0x1(%rax), %eax
movl %eax, -0x58(%rbp)
movl -0x58(%rbp), %eax
shll $0x8, %eax
movq -0x10(%rbp), %rcx
movq %rcx, %rdx
addq $-0x1, %rdx
movq %rdx, -0x10(%rbp)
movzbl -0x1(%rcx), %ecx
orl %ecx, %eax
movl %eax, -0x58(%rbp)
jmp 0x66b6
movl -0x54(%rbp), %eax
movl %eax, %ecx
addl $-0x1, %ecx
movl %ecx, -0x54(%rbp)
cmpl $0x0, %eax
je 0x66e5
movq -0x50(%rbp), %rax
addq $-0x4, %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
movslq -0x58(%rbp), %rcx
movl (%rax,%rcx,4), %ecx
movq -0x50(%rbp), %rax
movl %ecx, (%rax)
jmp 0x66b6
jmp 0x6471
movq -0x48(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x70, %rsp
popq %rbp
retq
nopl (%rax)