// File: /workspace/github_c_makefile_star2_O3/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
movl %r8d, -0x2c(%rbp)
movl %ecx, -0x30(%rbp)
movq 0x80(%rdi), %rax
cmpq $0xfffffff, %rax        # imm = 0xFFFFFFF
jbe 0x48b6
movq 0x10(%rbp), %rax
movl $0x0, (%rax)
xorl %eax, %eax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %r9, %rbx
movq %rdi, %r12
movslq %esi, %rcx
movq %rcx, -0x48(%rbp)
movslq %edx, %rcx
movq %rcx, -0x40(%rbp)
incq %rax
movq %rax, 0x80(%r12)
cmpq $0x7fffff, 0x48(%r12)   # imm = 0x7FFFFF
ja 0x489b
movq %r12, %rdi
movl -0x30(%rbp), %esi
callq 0x3932
addq -0x48(%rbp), %rax
cmpq $0xffff, %rax           # imm = 0xFFFF
ja 0x489b
movq 0x28(%r12), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rax
movq (%rax), %rsi
movzbl 0x8(%rax), %r13d
cmpl $0x11, %r13d
jb 0x4986
movq 0x80(%r12), %rcx
cmpq $0xfffffff, %rcx        # imm = 0xFFFFFFF
ja 0x489b
movslq 0xc(%rax), %r14
incq %rcx
movq %rcx, 0x80(%r12)
cmpq $0x7fffff, 0x48(%r12)   # imm = 0x7FFFFF
ja 0x489b
movq %r12, %rdi
callq 0x38bc
addl $-0x10, %r13d
movq %r12, %rdi
movl %r13d, %esi
callq 0x3932
addq %r14, %rax
cmpq $0xffff, %rax           # imm = 0xFFFF
ja 0x489b
movq 0x28(%r12), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rax
movq (%rax), %rsi
movzbl 0x8(%rax), %r13d
cmpl $0x10, %r13d
ja 0x4912
cmpq $0x7fffff, 0x48(%r12)   # imm = 0x7FFFFF
ja 0x489b
movq 0x10(%rax), %r14
movq %r12, %rdi
callq 0x38bc
cmpb $0x10, %r13b
jne 0x49c9
movq 0x10(%rbp), %rax
movslq (%rax), %rax
cmpq $0x7fffff, %rax         # imm = 0x7FFFFF
jg 0x489b
movb %r14b, (%rbx,%rax)
movq 0x10(%rbp), %rax
incl (%rax)
jmp 0x4b12
cmpb $0xe, %r13b
ja 0x4b2b
movq %r14, -0x38(%rbp)
movq %r12, %rdi
movl %r13d, %esi
callq 0x38bc
movq %rax, %r13
movq %r12, %rdi
movl -0x2c(%rbp), %esi
callq 0x3932
addq -0x40(%rbp), %rax
cmpq $0xffff, %rax           # imm = 0xFFFF
ja 0x489b
movq 0x28(%r12), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rax
movq (%rax), %rsi
movzbl 0x8(%rax), %r14d
cmpl $0x11, %r14d
jb 0x4a8f
movq 0x80(%r12), %rcx
cmpq $0xfffffff, %rcx        # imm = 0xFFFFFFF
ja 0x489b
movslq 0xc(%rax), %r15
incq %rcx
movq %rcx, 0x80(%r12)
cmpq $0x7fffff, 0x48(%r12)   # imm = 0x7FFFFF
ja 0x489b
movq %r12, %rdi
callq 0x38bc
addl $-0x10, %r14d
movq %r12, %rdi
movl %r14d, %esi
callq 0x3932
addq %r15, %rax
cmpq $0xffff, %rax           # imm = 0xFFFF
ja 0x489b
movq 0x28(%r12), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rax
movq (%rax), %rsi
movzbl 0x8(%rax), %r14d
cmpl $0x10, %r14d
ja 0x4a1b
cmpq $0x7fffff, 0x48(%r12)   # imm = 0x7FFFFF
ja 0x489b
addq -0x38(%rbp), %r13
movq 0x10(%rax), %r15
movq %r12, %rdi
callq 0x38bc
movq %r12, %rdi
movl %r14d, %esi
callq 0x38bc
movq 0x10(%rbp), %rcx
movslq (%rcx), %rcx
addq %r15, %rax
movq %rcx, %rdx
subq %rax, %rdx
addq %rdx, %r13
movslq %edx, %rax
cmpq %rax, %r13
jbe 0x4b12
cmpq $0x800000, %r13         # imm = 0x800000
ja 0x489b
cmpq $0x800000, %rdx         # imm = 0x800000
ja 0x489b
orq %r13, %rdx
js 0x489b
movq 0x10(%rbp), %rsi
movb (%rbx,%rax), %dl
movslq %ecx, %rcx
movb %dl, (%rbx,%rcx)
movl (%rsi), %ecx
incl %ecx
movl %ecx, (%rsi)
incq %rax
cmpq %rax, %r13
ja 0x4afb
movq 0x80(%r12), %rax
cmpq $0x10000000, %rax       # imm = 0x10000000
jb 0x48ca
jmp 0x489b
movb $0x1, %al
jmp 0x48a7
nop