// File: /workspace/github_c_makefile_star2_O3/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 $0x48, %rsp
movq %rdx, -0x38(%rbp)
movq %rsi, -0x60(%rbp)
movq %rdi, %r14
xorps %xmm0, %xmm0
movups %xmm0, 0x5c(%rdi)
movl $0x0, 0x6b(%rdi)
movl $0x5, %esi
callq 0x38bc
addl $0x101, %eax            # imm = 0x101
movw %ax, 0x70(%r14)
movq %r14, %rdi
movl $0x5, %esi
callq 0x38bc
incb %al
movb %al, 0x72(%r14)
movq %r14, %rdi
movl $0x4, %esi
callq 0x38bc
addl $0x4, %eax
andl $0xff, %eax
je 0x3e69
movl %eax, %ebx
xorl %r15d, %r15d
leaq 0x6576(%rip), %r12      # 0xa3c0
movq %r14, %rdi
movl $0x3, %esi
callq 0x38bc
movzbl (%r15,%r12), %ecx
movb %al, 0x5c(%r14,%rcx)
incq %r15
cmpq %r15, %rbx
jne 0x3e4a
subq $0x8, %rsp
leaq -0x50(%rbp), %rax
leaq -0x54(%rbp), %r8
leaq -0x2b(%rbp), %r10
movq %r14, %rdi
movl $0x2, %esi
movl $0x13, %edx
movl $0x2, %ecx
movl $0x7, %r9d
pushq %rax
pushq %r8
pushq %r10
callq 0x413a
addq $0x20, %rsp
movq 0x78(%r14), %rdi
testq %rdi, %rdi
je 0x3eb5
callq 0x21e0
movq $0x0, 0x78(%r14)
movl $0x7fff8, %edi          # imm = 0x7FFF8
callq 0x2030
movq %rax, 0x78(%r14)
movzbl 0x72(%r14), %eax
orw 0x70(%r14), %ax
je 0x4060
movl -0x54(%rbp), %eax
movl %eax, -0x3c(%rbp)
movslq -0x50(%rbp), %rax
xorl %r12d, %r12d
movq %rax, -0x68(%rbp)
leaq (%rax,%rax,2), %rbx
xorl %r15d, %r15d
movq 0x80(%r14), %rax
cmpq $0x10000000, %rax       # imm = 0x10000000
jae 0x4104
incq %rax
movq %rax, 0x80(%r14)
movq %r14, %rdi
movl -0x3c(%rbp), %esi
callq 0x3932
movq %rax, %r13
movq -0x68(%rbp), %rax
addq %r13, %rax
cmpq $0x10000, %rax          # imm = 0x10000
jae 0x4104
cmpq $0x800000, 0x48(%r14)   # imm = 0x800000
jae 0x4104
movq 0x28(%r14), %rcx
leaq (%rax,%rax,2), %rax
movl (%rcx,%rax,8), %esi
movq %r14, %rdi
callq 0x38bc
leaq (,%r13,2), %rax
addq %r13, %rax
shlq $0x3, %rax
addq 0x28(%r14), %rax
cmpl $0x0, 0xc(%rax,%rbx,8)
je 0x3f84
movq %r15, %rax
movzwl 0x70(%r14), %ecx
movzbl 0x72(%r14), %edx
addl %ecx, %edx
movq %rax, %r15
cmpl %edx, %r12d
jl 0x3eeb
jmp 0x4060
movq 0x10(%rax,%rbx,8), %rax
cmpq $0xf, %rax
ja 0x3f9f
movq 0x78(%r14), %rcx
movslq %r12d, %rdx
movq %rax, (%rcx,%rdx,8)
incl %r12d
jmp 0x3f67
cmpq $0x11, %rax
je 0x3fde
cmpq $0x10, %rax
jne 0x4021
movq %r14, %rdi
movl $0x2, %esi
callq 0x38bc
addl $0x3, %eax
testl %eax, %eax
jle 0x3f64
movslq %r12d, %rcx
shlq $0x3, %rcx
addq 0x78(%r14), %rcx
movl %eax, %eax
xorl %edx, %edx
movq %r15, (%rcx,%rdx,8)
incq %rdx
cmpl %edx, %eax
jne 0x3fce
addl %edx, %r12d
jmp 0x3f64
movq %r14, %rdi
movl $0x3, %esi
callq 0x38bc
movq %rax, %r13
addl $0x3, %eax
testl %eax, %eax
jle 0x3f64
movslq %r12d, %r12
leaq (,%r12,8), %rdi
addq 0x78(%r14), %rdi
movl %eax, %edx
shlq $0x3, %rdx
xorl %esi, %esi
callq 0x20f0
addl %r13d, %r12d
addl $0x3, %r12d
jmp 0x3f64
movq %r14, %rdi
movl $0x7, %esi
callq 0x38bc
movq %rax, %r13
addl $0xb, %eax
testl %eax, %eax
jle 0x3f64
movslq %r12d, %rdi
shlq $0x3, %rdi
addq 0x78(%r14), %rdi
movl %eax, %edx
shlq $0x3, %rdx
xorl %esi, %esi
callq 0x20f0
addl %r13d, %r12d
addl $0xb, %r12d
jmp 0x3f64
subq $0x8, %rsp
leaq -0x44(%rbp), %rax
leaq -0x4c(%rbp), %r8
leaq -0x2a(%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 0x413a
addq $0x20, %rsp
subq $0x8, %rsp
leaq -0x40(%rbp), %rax
leaq -0x48(%rbp), %r8
leaq -0x29(%rbp), %r10
movq %r14, %rdi
movl $0x4, %esi
xorl %edx, %edx
movl $0x1, %ecx
movl $0x6, %r9d
pushq %rax
pushq %r8
pushq %r10
callq 0x413a
addq $0x20, %rsp
movl -0x44(%rbp), %esi
movl -0x40(%rbp), %edx
movl -0x4c(%rbp), %ecx
movl -0x48(%rbp), %r8d
subq $0x8, %rsp
movq %r14, %rdi
movq -0x60(%rbp), %r9
pushq -0x38(%rbp)
callq 0x4874
addq $0x10, %rsp
movq 0x78(%r14), %rdi
testq %rdi, %rdi
je 0x4100
callq 0x21e0
movq $0x0, 0x78(%r14)
movb $0x1, %al
jmp 0x4110
movq -0x38(%rbp), %rax
movl $0x0, (%rax)
xorl %eax, %eax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x4121
movq %rax, %rdi
callq 0x20b0
movq -0x38(%rbp), %rax
movl $0x0, (%rax)
callq 0x2280
jmp 0x410e