// File: /workspace/github_c_makefile_star2_O1/DavidSM64[P]DKR-Decompressor/GECompression.cpp
// Function: GECompression::DecompressBasedOnTable(int, int, int, int, unsigned char*, int&)
bool GECompression::DecompressBasedOnTable(int startIndex1, int startIndex2, int bitLen1, int bitLen2, unsigned char* returnBuffer, int& fileSize)
{
	unsigned long index = 0;
	bool exitFlag = 1;

	try
	{

	while (exitFlag)
	{

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

		if (bytesIndex >= maxByteSize)
		{
			fileSize = 0;
			return false;
		}
		index = GetNBitsAndPreserve(bitLen1);
		if ((startIndex1 + index) > 0xFFFF)
		{
			fileSize = 0;
			return false;
		}
		tableEntry entry = unpackTable[startIndex1 + index];

		while (entry.flags > 0x10)
		{
			if (iterationCounter > 268435455)
			{
				fileSize = 0;
				return false;
			}
			iterationCounter++;

			if (bytesIndex >= maxByteSize)
			{
				fileSize = 0;
				return false;
			}
			GetNBits(entry.bits); // discard
			index = GetNBitsAndPreserve(entry.flags-0x10);
			if ((entry.nextIndex+index) > 0xFFFF)
			{
				fileSize = 0;
				return false;
			}
			entry = unpackTable[entry.nextIndex+index];
		}
		if (bytesIndex >= maxByteSize)
		{
			fileSize = 0;
			return false;
		}
		GetNBits(entry.bits); // discard
		
		if (entry.flags==0x10)
		{
			if (fileSize >= maxByteSize)
			{
				fileSize = 0;
				return false;
			}
			returnBuffer[fileSize] = entry.wordValue;
			fileSize++;
		}
		else if (entry.flags < 0xf)
		{
			unsigned long copyLen = entry.wordValue + GetNBits(entry.flags);
			unsigned long index2 = GetNBitsAndPreserve(bitLen2);
			if ((startIndex2+index2) > 0xFFFF)
			{
				fileSize = 0;
				return false;
			}
			tableEntry entry2 = unpackTable[startIndex2+index2];
			while (entry2.flags>0x10)
			{

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

				if (bytesIndex >= maxByteSize)
				{
					fileSize = 0;
					return false;
				}
				GetNBits(entry2.bits); // discard
				index2 = GetNBitsAndPreserve(entry2.flags-0x10);
				if ((entry2.nextIndex+index2) > 0xFFFF)
				{
					fileSize = 0;
					return false;
				}
				entry2 = unpackTable[entry2.nextIndex+index2];
			}
			if (bytesIndex >= maxByteSize)
			{
				fileSize = 0;
				return false;
			}
			GetNBits(entry2.bits); // discard

			unsigned long endOffset1 = entry2.wordValue;
			unsigned long endOffset2 = GetNBits(entry2.flags);
			unsigned long start = fileSize-endOffset1-endOffset2;
			unsigned long end = start + copyLen;
			for (int x = start; x < end; x++)
			{
				if ((((signed long) start) < 0) || ((((signed long) end) < 0)) || ((start > maxByteSize)) || ((end > maxByteSize)))
				{
					fileSize = 0;
					return false;
				}
				returnBuffer[fileSize] = returnBuffer[x];
				fileSize++;
			}
		}
		else
			exitFlag = 0;
	}

	} catch (...)
	{
		return false;
	}
	return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movq %r9, -0x38(%rbp)
movl %r8d, -0x2c(%rbp)
movl %ecx, -0x30(%rbp)
movq %rdi, %r13
movq 0x10(%rbp), %rbx
movslq %esi, %rax
movq %rax, -0x50(%rbp)
movslq %edx, %rax
movq %rax, -0x48(%rbp)
movb $0x1, %r15b
movl %r15d, %r12d
testb $0x1, %r15b
je 0x4c2d
movq 0x80(%r13), %rax
cmpq $0xfffffff, %rax        # imm = 0xFFFFFFF
ja 0x4c27
incq %rax
movq %rax, 0x80(%r13)
cmpq $0x7fffff, 0x48(%r13)   # imm = 0x7FFFFF
ja 0x4c27
movq %r13, %rdi
movl -0x30(%rbp), %esi
callq 0x399c
addq -0x50(%rbp), %rax
cmpq $0xffff, %rax           # imm = 0xFFFF
ja 0x4c27
movq 0x28(%r13), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rax
movq (%rax), %rsi
movzbl 0x8(%rax), %r14d
cmpl $0x11, %r14d
jb 0x4a65
movq 0x80(%r13), %rcx
cmpq $0xfffffff, %rcx        # imm = 0xFFFFFFF
ja 0x4c06
movslq 0xc(%rax), %rbx
incq %rcx
movq %rcx, 0x80(%r13)
cmpq $0x7fffff, 0x48(%r13)   # imm = 0x7FFFFF
ja 0x4c06
movq %r13, %rdi
callq 0x3928
addl $-0x10, %r14d
movq %r13, %rdi
movl %r14d, %esi
callq 0x399c
addq %rbx, %rax
cmpq $0xffff, %rax           # imm = 0xFFFF
ja 0x4c06
movq 0x28(%r13), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rax
movq (%rax), %rsi
movzbl 0x8(%rax), %r14d
cmpl $0x10, %r14d
ja 0x49f5
xorl %r15d, %r15d
cmpq $0x7fffff, 0x48(%r13)   # imm = 0x7FFFFF
movl $0x0, %ecx
ja 0x4c0b
movq 0x10(%rax), %rbx
movq %r13, %rdi
callq 0x3928
cmpb $0x10, %r14b
jne 0x4ac0
movq 0x10(%rbp), %rax
movslq (%rax), %rax
xorl %r15d, %r15d
movl $0x0, %ecx
cmpq $0x7fffff, %rax         # imm = 0x7FFFFF
jg 0x4c0b
movq -0x38(%rbp), %rcx
movb %bl, (%rcx,%rax)
movq 0x10(%rbp), %rax
movl (%rax), %r15d
incl %r15d
movb $0x1, %cl
jmp 0x4c0b
movb $0x1, %al
xorl %r15d, %r15d
cmpb $0xe, %r14b
ja 0x4c21
movq %rbx, -0x40(%rbp)
movq %r13, %rdi
movl %r14d, %esi
callq 0x3928
movq %rax, %r14
movq %r13, %rdi
movl -0x2c(%rbp), %esi
callq 0x399c
addq -0x48(%rbp), %rax
movl $0x0, %ecx
cmpq $0xffff, %rax           # imm = 0xFFFF
ja 0x4c0b
movq 0x28(%r13), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rax
movq (%rax), %rsi
movzbl 0x8(%rax), %ebx
cmpl $0x11, %ebx
jb 0x4b85
movq 0x80(%r13), %rcx
cmpq $0xfffffff, %rcx        # imm = 0xFFFFFFF
ja 0x4c06
movslq 0xc(%rax), %r15
incq %rcx
movq %rcx, 0x80(%r13)
cmpq $0x7fffff, 0x48(%r13)   # imm = 0x7FFFFF
ja 0x4c06
movq %r13, %rdi
callq 0x3928
addl $-0x10, %ebx
movq %r13, %rdi
movl %ebx, %esi
callq 0x399c
addq %r15, %rax
cmpq $0xffff, %rax           # imm = 0xFFFF
ja 0x4c06
movq 0x28(%r13), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rax
movq (%rax), %rsi
movzbl 0x8(%rax), %ebx
cmpl $0x10, %ebx
ja 0x4b19
xorl %r15d, %r15d
cmpq $0x7fffff, 0x48(%r13)   # imm = 0x7FFFFF
movl $0x0, %ecx
ja 0x4c0b
addq -0x40(%rbp), %r14
movq 0x10(%rax), %r15
movq %r13, %rdi
callq 0x3928
movq %r13, %rdi
movl %ebx, %esi
callq 0x3928
movq 0x10(%rbp), %rbx
movslq (%rbx), %rcx
addq %r15, %rax
subq %rax, %rcx
addq %rcx, %r14
movslq %ecx, %rax
cmpq %rax, %r14
jbe 0x4bff
xorl %r15d, %r15d
cmpq $0x800000, %r14         # imm = 0x800000
ja 0x4c09
cmpq $0x800000, %rcx         # imm = 0x800000
ja 0x4c09
orq %r14, %rcx
movl $0x0, %ecx
js 0x4c0b
movq -0x38(%rbp), %rsi
movb (%rsi,%rax), %cl
movslq (%rbx), %rdx
movb %cl, (%rsi,%rdx)
incl (%rbx)
incq %rax
cmpq %rax, %r14
ja 0x4bec
movl %r12d, %r15d
movb $0x1, %al
jmp 0x4c17
xorl %r15d, %r15d
xorl %ecx, %ecx
movq 0x10(%rbp), %rbx
movl %r15d, (%rbx)
movl %ecx, %eax
movl %r12d, %r15d
testb %al, %al
jne 0x4988
jmp 0x4c2d
movq 0x10(%rbp), %rbx
jmp 0x4c17
movl $0x0, (%rbx)
notb %r12b
andb $0x1, %r12b
movl %r12d, %eax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop