// File: /workspace/github_c_makefile_star2_O1/DavidSM64[P]DKR-Decompressor/GECompression.cpp
// Function: GECompression::UncompressType2(unsigned char*, int&)
bool GECompression::UncompressType2(unsigned char* returnBuffer, int& fileSize)
{
	try
	{

	for (int x = 0; x < 0x13; x++)
	{
		variableTable[x] = 0;
	}

	tableSize = (GetNBits(5)+0x101);
	fiveBits = GetNBits(5)+0x1;
	unsigned char fourBits = GetNBits(4)+0x4;

	for (int index = 0; index < fourBits; index++)
	{
		unsigned char threeBits = GetNBits(3);
		variableTable[bt2Table1B[index]] = threeBits;
	}

	bool returnValue1;
	int numBits1;
	int startIndex1;

	CreateGlobalDecompressionTable(2, 0x13, 2, 2, 7, returnValue1, numBits1, startIndex1);

	if (wordTable != NULL)
	{
		delete [] wordTable;
		wordTable = NULL;
	}
	wordTable = new unsigned long[0xFFFF];

	int wordTableSpot = 0;

	unsigned long lastWritten = 0;
	while (wordTableSpot < (tableSize + fiveBits))
	{

		if (iterationCounter > 268435455)
		{
			fileSize = 0;
			return false;
		}
		iterationCounter++;

		unsigned long tableIndex = GetNBitsAndPreserve(numBits1);
		if ((startIndex1 + tableIndex) > 0xFFFF)
		{
			fileSize = 0;
			return false;
		}
		int numBits2 = unpackTable[startIndex1 + tableIndex].bits;
		if (bytesIndex >= maxByteSize)
		{
			fileSize = 0;
			return false;
		}
		GetNBits(numBits2);
		unsigned long wordValue = unpackTable[startIndex1 + tableIndex].wordValue;
		if (unpackTable[startIndex1 + tableIndex].nextIndex == 0)
		{
			if (wordValue < 0x10)
			{
				lastWritten = wordValue;
				wordTable[wordTableSpot] = wordValue;
				wordTableSpot++;
			}
			else if (wordValue == 0x10)
			{
				int repeatLen = (GetNBits(2) + 3);
				for (int index = 0; index < repeatLen; index++)
				{
					wordTable[wordTableSpot] = lastWritten;
					wordTableSpot++;
				}
			}
			else if (wordValue == 0x11)
			{
				int repeatLen = (GetNBits(3) + 3);
				for (int index = 0; index < repeatLen; index++)
				{
					wordTable[wordTableSpot] = 0;
					wordTableSpot++;					
				}
			}
			else
			{
				int repeatLen = (GetNBits(7) + 0xB);
				for (int index = 0; index < repeatLen; index++)
				{
					wordTable[wordTableSpot] = 0;
					wordTableSpot++;					
				}
			}
		}
	}
	bool returnValue2, returnValue3;
	int numBits2, numBits3;
	int startIndex2, startIndex3;

	CreateGlobalDecompressionTable(3, 0x101, 0, 0, 9, returnValue2, numBits2, startIndex2);

	CreateGlobalDecompressionTable(4, 0, 1, 1, 6, returnValue3, numBits3, startIndex3);
	DecompressBasedOnTable(startIndex2, startIndex3, numBits2, numBits3, returnBuffer, fileSize);
	if (wordTable != NULL)
	{
		delete [] wordTable;
		wordTable = NULL;
	}
	} catch (...)
	{
		fileSize = 0;
		return false;
	}
	return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %rdx, -0x40(%rbp)
movq %rsi, %r13
movq %rdi, %r14
xorps %xmm0, %xmm0
movups %xmm0, 0x5c(%rdi)
movl $0x0, 0x6b(%rdi)
movl $0x5, %esi
callq 0x3928
addl $0x101, %eax            # imm = 0x101
movw %ax, 0x70(%r14)
movq %r14, %rdi
movl $0x5, %esi
callq 0x3928
incb %al
movb %al, 0x72(%r14)
movq %r14, %rdi
movl $0x4, %esi
callq 0x3928
addl $0x4, %eax
andl $0xff, %eax
je 0x3e98
movl %eax, %ebx
xorl %r15d, %r15d
leaq 0x6547(%rip), %r12      # 0xa3c0
movq %r14, %rdi
movl $0x3, %esi
callq 0x3928
movzbl (%r15,%r12), %ecx
movb %al, 0x5c(%r14,%rcx)
incq %r15
cmpq %r15, %rbx
jne 0x3e79
subq $0x8, %rsp
leaq -0x60(%rbp), %rax
leaq -0x64(%rbp), %r8
leaq -0x33(%rbp), %r10
movq %r14, %rdi
movl $0x2, %esi
movl $0x13, %edx
movl $0x2, %ecx
movl $0x7, %r9d
pushq %rax
pushq %r8
pushq %r10
callq 0x4194
addq $0x20, %rsp
movq 0x78(%r14), %rdi
testq %rdi, %rdi
je 0x3ee4
callq 0x21e0
movq $0x0, 0x78(%r14)
movl $0x7fff8, %edi          # imm = 0x7FFF8
callq 0x2030
movq %r13, -0x70(%rbp)
movq %rax, 0x78(%r14)
movl -0x64(%rbp), %eax
movl %eax, -0x4c(%rbp)
movslq -0x60(%rbp), %rax
xorl %r13d, %r13d
movq %rax, -0x78(%rbp)
leaq (%rax,%rax,2), %rsi
movq $0x0, -0x30(%rbp)
movzwl 0x70(%r14), %eax
movzbl 0x72(%r14), %ecx
addl %eax, %ecx
cmpl %ecx, -0x30(%rbp)
setge %r12b
jge 0x40b7
movq 0x80(%r14), %rax
cmpq $0x10000000, %rax       # imm = 0x10000000
jae 0x4159
movq %rsi, %rbx
incq %rax
movq %rax, 0x80(%r14)
movq %r14, %rdi
movl -0x4c(%rbp), %esi
callq 0x399c
movq %rax, %r15
movq -0x78(%rbp), %rax
addq %r15, %rax
cmpq $0x10000, %rax          # imm = 0x10000
jae 0x3fc4
cmpq $0x800000, 0x48(%r14)   # imm = 0x800000
jae 0x3fc4
movq 0x28(%r14), %rcx
leaq (%rax,%rax,2), %rax
movl (%rcx,%rax,8), %esi
movq %r14, %rdi
callq 0x3928
leaq (%r15,%r15,2), %rax
shlq $0x3, %rax
addq 0x28(%r14), %rax
movb $0x1, %r15b
movq %rbx, %rsi
cmpl $0x0, 0xc(%rax,%rbx,8)
jne 0x3fd4
movq 0x10(%rax,%rsi,8), %rax
cmpq $0xf, %rax
ja 0x3fe2
movq 0x78(%r14), %rcx
movq -0x30(%rbp), %rdi
movslq %edi, %rdx
movq %rax, (%rcx,%rdx,8)
incl %edi
movq %rdi, -0x30(%rbp)
movq %rax, %r13
jmp 0x3fd4
movq -0x40(%rbp), %rax
movl $0x0, (%rax)
xorl %r15d, %r15d
movq %rbx, %rsi
testb %r15b, %r15b
jne 0x3f13
jmp 0x4163
cmpq $0x11, %rax
je 0x402c
cmpq $0x10, %rax
jne 0x406c
movq %r14, %rdi
movl $0x2, %esi
callq 0x3928
addl $0x3, %eax
testl %eax, %eax
jle 0x3fd1
movslq -0x30(%rbp), %rcx
shlq $0x3, %rcx
addq 0x78(%r14), %rcx
movl %eax, %eax
xorl %edx, %edx
movq %rbx, %rsi
movq %r13, (%rcx,%rdx,8)
incq %rdx
cmpl %edx, %eax
jne 0x4015
movq -0x30(%rbp), %rax
addl %edx, %eax
movq %rax, -0x30(%rbp)
jmp 0x3fd4
movq %r14, %rdi
movl $0x3, %esi
callq 0x3928
leal 0x3(%rax), %ecx
testl %ecx, %ecx
jle 0x3fd1
movslq -0x30(%rbp), %rdi
shlq $0x3, %rdi
addq 0x78(%r14), %rdi
movl %ecx, %edx
shlq $0x3, %rdx
xorl %esi, %esi
movq %rax, -0x48(%rbp)
callq 0x20f0
movq -0x30(%rbp), %rax
movq -0x48(%rbp), %rcx
addl %ecx, %eax
addl $0x3, %eax
jmp 0x40ae
movq %r14, %rdi
movl $0x7, %esi
callq 0x3928
leal 0xb(%rax), %ecx
testl %ecx, %ecx
jle 0x3fd1
movslq -0x30(%rbp), %rdi
shlq $0x3, %rdi
addq 0x78(%r14), %rdi
movl %ecx, %edx
shlq $0x3, %rdx
xorl %esi, %esi
movq %rax, -0x48(%rbp)
callq 0x20f0
movq -0x30(%rbp), %rax
movq -0x48(%rbp), %rcx
addl %ecx, %eax
addl $0xb, %eax
movq %rax, -0x30(%rbp)
jmp 0x3fd1
subq $0x8, %rsp
leaq -0x54(%rbp), %rax
leaq -0x5c(%rbp), %r8
leaq -0x32(%rbp), %r10
movq %r14, %rdi
movl $0x3, %esi
movl $0x101, %edx            # imm = 0x101
xorl %ecx, %ecx
movl $0x9, %r9d
pushq %rax
pushq %r8
pushq %r10
callq 0x4194
addq $0x20, %rsp
subq $0x8, %rsp
leaq -0x50(%rbp), %rax
leaq -0x58(%rbp), %r8
leaq -0x31(%rbp), %r10
movq %r14, %rdi
movl $0x4, %esi
xorl %edx, %edx
movl $0x1, %ecx
movl $0x6, %r9d
pushq %rax
pushq %r8
pushq %r10
callq 0x4194
addq $0x20, %rsp
movl -0x54(%rbp), %esi
movl -0x50(%rbp), %edx
movl -0x5c(%rbp), %ecx
movl -0x58(%rbp), %r8d
subq $0x8, %rsp
movq %r14, %rdi
movq -0x70(%rbp), %r9
pushq -0x40(%rbp)
callq 0x4954
addq $0x10, %rsp
movq 0x78(%r14), %rdi
testq %rdi, %rdi
je 0x4163
callq 0x21e0
movq $0x0, 0x78(%r14)
jmp 0x4163
movq -0x40(%rbp), %rax
movl $0x0, (%rax)
movl %r12d, %eax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x4177
movq %rax, %rdi
callq 0x20b0
movq -0x40(%rbp), %rax
movl $0x0, (%rax)
callq 0x2280
xorl %r12d, %r12d
jmp 0x4163
nop