// File: /workspace/github_cpp_makefile_star2_O3/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
pushq %r15
pushq %r14
pushq %rbx
subq $0x18, %rsp
movq %rdx, %rbx
movl %esi, %ebp
movq %rdi, %r14
movq %rsp, %rdi
movq %r14, %rsi
movl %ebp, %edx
callq 0x545a
testq %rax, %rax
je 0x582d
movl 0x4(%rax), %r15d
testq %rbx, %rbx
jne 0x5718
testq %r15, %r15
je 0x582d
movl %r15d, %edi
andl $-0x4, %edi
callq 0x4040
movq %rax, %rbx
cmpl $0x4, %r15d
jb 0x582f
movslq %ebp, %rax
addq %rax, %r14
andl $-0x4, %r15d
addq %rbx, %r15
leaq 0xc8f6(%rip), %rax      # 0x1202c
movzbl -0x1(%r14), %edx
movl %edx, %ecx
andl $0x3, %ecx
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
testb $0x8, %dl
jne 0x57c2
decq %r14
movl %edx, %ecx
shrl $0x4, %ecx
incl %ecx
jmp 0x57cf
shrl $0x2, %edx
incl %edx
movzwl -0x3(%r14), %ecx
addq $-0x3, %r14
jmp 0x5798
shll $0x6, %edx
andl $0x3f00, %edx           # imm = 0x3F00
movzbl -0x2(%r14), %edi
leaq -0x4(%r14), %rsi
orl %edx, %edi
je 0x57ae
movzwl -0x4(%r14), %ecx
jmp 0x579d
shrl $0x2, %edx
incl %edx
movzbl -0x2(%r14), %ecx
addq $-0x2, %r14
incq %rcx
movq %r14, %rsi
movl %edx, %edi
movl -0x4(%r15,%rcx,4), %edx
movl %edx, -0x4(%r15)
addq $-0x4, %r15
decl %edi
jne 0x579d
movq %r15, %rdx
movq %rsi, %r14
movq %rdx, %r15
cmpq %rbx, %rdx
ja 0x5736
jmp 0x582f
movl %edx, %ecx
shll $0x4, %ecx
movb -0x2(%r14), %cl
addq $-0x2, %r14
testb $0x4, %dl
jne 0x57fb
movq %r15, %rdx
movq %r14, %rsi
testl %ecx, %ecx
je 0x57b1
leaq -0x1(%r14), %rsi
leaq -0x4(%r15), %rdx
movzbl -0x1(%r14), %edi
movl %edi, -0x4(%r15)
movq %rsi, %r14
movq %rdx, %r15
decl %ecx
jne 0x57de
jmp 0x57b1
testl %ecx, %ecx
je 0x5825
shll $0x2, %ecx
movq $-0x4, %rsi
xorl %edx, %edx
movl (%r14,%rsi), %edi
movl %edi, (%r15,%rsi)
addq $-0x4, %rsi
addq $0x4, %rdx
cmpl %edx, %ecx
jne 0x580b
subq %rdx, %r14
subq %rdx, %r15
movq %r15, %rdx
movq %r14, %rsi
jmp 0x57b1
xorl %ebx, %ebx
movq %rbx, %rax
addq $0x18, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
nop