// File: /workspace/github_cpp_makefile_star2_O2/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, %r14
movl %esi, %ebp
movq %rdi, %rbx
movq %rsp, %rdi
movq %rbx, %rsi
movl %ebp, %edx
callq 0x4278
testq %rax, %rax
je 0x44fc
movl 0x4(%rax), %r15d
testq %r14, %r14
jne 0x4513
testl %r15d, %r15d
je 0x450d
movl %r15d, %edi
andl $-0x4, %edi
callq 0x3040
movq %rax, %r14
jmp 0x4513
xorl %r14d, %r14d
movq %r14, %rax
addq $0x18, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
xorl %r15d, %r15d
xorl %r14d, %r14d
andl $-0x4, %r15d
addq %r14, %r15
movslq %ebp, %rax
addq %rax, %rbx
leaq 0xab05(%rip), %rax      # 0xf02c
cmpq %r14, %r15
jbe 0x44ff
movzbl -0x1(%rbx), %ecx
movl %ecx, %edx
andl $0x3, %edx
movslq (%rax,%rdx,4), %rdx
addq %rax, %rdx
jmpq *%rdx
testb $0x8, %cl
jne 0x4594
decq %rbx
movl %ecx, %edx
shrl $0x4, %edx
incl %edx
jmp 0x45a0
shrl $0x2, %ecx
incl %ecx
movzwl -0x3(%rbx), %edx
addq $-0x3, %rbx
jmp 0x458d
shll $0x6, %ecx
movb -0x2(%rbx), %cl
movzwl -0x4(%rbx), %edx
addq $-0x4, %rbx
jmp 0x458d
shrl $0x2, %ecx
incl %ecx
movzbl -0x2(%rbx), %edx
addq $-0x2, %rbx
incq %rdx
jmp 0x458d
movl -0x4(%r15,%rdx,4), %esi
movl %esi, -0x4(%r15)
addq $-0x4, %r15
subl $0x1, %ecx
jae 0x4580
jmp 0x4527
movl %ecx, %edx
shll $0x4, %edx
movb -0x2(%rbx), %dl
addq $-0x2, %rbx
testb $0x4, %cl
jne 0x45bf
subl $0x1, %edx
jb 0x4527
movzbl -0x1(%rbx), %ecx
decq %rbx
movl %ecx, -0x4(%r15)
addq $-0x4, %r15
jmp 0x45a5
subl $0x1, %edx
jb 0x4527
movl -0x4(%rbx), %ecx
addq $-0x4, %rbx
movl %ecx, -0x4(%r15)
addq $-0x4, %r15
jmp 0x45bf
nop