// File: FreeSlave[P]vhlt/common/bspfile.cpp
// Function: DecompressVis(unsigned char const*, unsigned char*, unsigned int)
void            DecompressVis(const byte* src, byte* const dest, const unsigned int dest_length)
{
    unsigned int    current_length = 0;
    int             c;
    byte*           out;
    int             row;

#ifdef ZHLT_DecompressVis_FIX
	row = (g_dmodels[0].visleafs + 7) >> 3; // same as the length used by VIS program in CompressVis
	// The wrong size will cause DecompressVis to spend extremely long time once the source pointer runs into the invalid area in g_dvisdata (for example, in BuildFaceLights, some faces could hang for a few seconds), and sometimes to crash.
#else
    row = (g_numleafs + 7) >> 3;
#endif
    out = dest;

    do
    {
#ifdef ZHLT_DecompressVis_FIX
		hlassume (src - g_dvisdata < g_visdatasize, assume_DECOMPRESSVIS_OVERFLOW);
#endif
        if (*src)
        {
            current_length++;
            hlassume(current_length <= dest_length, assume_DECOMPRESSVIS_OVERFLOW);

            *out = *src;
            out++;
            src++;
            continue;
        }
		
#ifdef ZHLT_DecompressVis_FIX
		hlassume (&src[1] - g_dvisdata < g_visdatasize, assume_DECOMPRESSVIS_OVERFLOW);
#endif
        c = src[1];
        src += 2;
        while (c)
        {
            current_length++;
            hlassume(current_length <= dest_length, assume_DECOMPRESSVIS_OVERFLOW);

            *out = 0;
            out++;
            c--;

            if (out - dest >= row)
            {
                return;
            }
        }
    }
    while (out - dest < row);
}

// Assembly:
subq $0x38, %rsp
movq %rdi, 0x30(%rsp)
movq %rsi, 0x28(%rsp)
movl %edx, 0x24(%rsp)
movl $0x0, 0x20(%rsp)
movl 0x328d4(%rip), %eax     # 0x37524
addl $0x7, %eax
sarl $0x3, %eax
movl %eax, 0xc(%rsp)
movq 0x28(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0x30(%rsp), %rax
leaq 0x3a890(%rip), %rcx     # 0x3f500
subq %rcx, %rax
movslq 0x3a87a(%rip), %rcx     # 0x3f4f4
cmpq %rcx, %rax
setl %al
movzbl %al, %edi
andl $0x1, %edi
movl $0x34, %esi
callq 0xc400
movq 0x30(%rsp), %rax
cmpb $0x0, (%rax)
je 0x4cef
movl 0x20(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x20(%rsp)
movl 0x20(%rsp), %eax
cmpl 0x24(%rsp), %eax
setbe %al
movzbl %al, %edi
andl $0x1, %edi
movl $0x34, %esi
callq 0xc400
movq 0x30(%rsp), %rax
movb (%rax), %cl
movq 0x10(%rsp), %rax
movb %cl, (%rax)
movq 0x10(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x10(%rsp)
movq 0x30(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x30(%rsp)
jmp 0x4da5
movq 0x30(%rsp), %rax
addq $0x1, %rax
leaq 0x3a801(%rip), %rcx     # 0x3f500
subq %rcx, %rax
movslq 0x3a7eb(%rip), %rcx     # 0x3f4f4
cmpq %rcx, %rax
setl %al
movzbl %al, %edi
andl $0x1, %edi
movl $0x34, %esi
callq 0xc400
movq 0x30(%rsp), %rax
movzbl 0x1(%rax), %eax
movl %eax, 0x1c(%rsp)
movq 0x30(%rsp), %rax
addq $0x2, %rax
movq %rax, 0x30(%rsp)
cmpl $0x0, 0x1c(%rsp)
je 0x4da3
movl 0x20(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x20(%rsp)
movl 0x20(%rsp), %eax
cmpl 0x24(%rsp), %eax
setbe %al
movzbl %al, %edi
andl $0x1, %edi
movl $0x34, %esi
callq 0xc400
movq 0x10(%rsp), %rax
movb $0x0, (%rax)
movq 0x10(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x10(%rsp)
movl 0x1c(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0x1c(%rsp)
movq 0x10(%rsp), %rax
movq 0x28(%rsp), %rcx
subq %rcx, %rax
movslq 0xc(%rsp), %rcx
cmpq %rcx, %rax
jl 0x4da1
jmp 0x4dc0
jmp 0x4d3a
jmp 0x4da5
movq 0x10(%rsp), %rax
movq 0x28(%rsp), %rcx
subq %rcx, %rax
movslq 0xc(%rsp), %rcx
cmpq %rcx, %rax
jl 0x4c64
addq $0x38, %rsp
retq
nopw %cs:(%rax,%rax)