// File: /workspace/github_cpp_makefile_star2_O1/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 0x546a
testq %rax, %rax
je 0x5714
movq %rax, %r15
testq %rbx, %rbx
jne 0x571a
movl 0x4(%r15), %edi
testq %rdi, %rdi
je 0x5718
andl $-0x4, %edi
callq 0x4040
movq %rax, %rbx
jmp 0x571a
xorl %ebx, %ebx
jmp 0x5724
xorl %ebx, %ebx
movl 0x4(%r15), %ecx
cmpq $0x4, %rcx
jae 0x5732
movq %rbx, %rax
addq $0x18, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
movslq %ebp, %rax
addq %rax, %r14
andl $-0x4, %ecx
addq %rbx, %rcx
leaq 0xc8e7(%rip), %rax      # 0x1202c
movzbl -0x1(%r14), %edx
movl %edx, %esi
andl $0x3, %esi
movslq (%rax,%rsi,4), %rsi
addq %rax, %rsi
jmpq *%rsi
testb $0x8, %dl
jne 0x57bf
decq %r14
movl %edx, %esi
shrl $0x4, %esi
incl %esi
jmp 0x57cc
shrl $0x2, %edx
incl %edx
movzwl -0x3(%r14), %esi
addq $-0x3, %r14
jmp 0x579c
shll $0x6, %edx
movb -0x2(%r14), %dl
movzwl -0x4(%r14), %esi
addq $-0x4, %r14
jmp 0x579c
shrl $0x2, %edx
incl %edx
movzbl -0x2(%r14), %esi
addq $-0x2, %r14
incq %rsi
testl %edx, %edx
je 0x57af
movl -0x4(%rcx,%rsi,4), %edi
movl %edi, -0x4(%rcx)
addq $-0x4, %rcx
decl %edx
jne 0x57a0
movq %rcx, %rdx
movq %rdx, %rcx
cmpq %rbx, %rdx
ja 0x5745
jmp 0x5724
movl %edx, %esi
shll $0x4, %esi
movb -0x2(%r14), %sil
addq $-0x2, %r14
movq %r14, %rdi
testb $0x4, %dl
jne 0x57f9
movq %rcx, %rdx
movq %rdi, %r14
testl %esi, %esi
je 0x57b2
leaq -0x1(%rdi), %r14
leaq -0x4(%rcx), %rdx
movzbl -0x1(%rdi), %edi
movl %edi, -0x4(%rcx)
movq %r14, %rdi
movq %rdx, %rcx
decl %esi
jne 0x57de
jmp 0x57b2
testl %esi, %esi
je 0x5822
shll $0x2, %esi
movq $-0x1, %r8
xorl %edx, %edx
movl (%rdi,%r8,4), %r9d
movl %r9d, (%rcx,%r8,4)
decq %r8
addq $0x4, %rdx
cmpl %edx, %esi
jne 0x5809
subq %rdx, %rdi
subq %rdx, %rcx
movq %rcx, %rdx
movq %rdi, %r14
jmp 0x57b2