// File: /workspace/github_cpp_makefile_star2_O1/divinity76[P]pi_compression/compressor/compressor.cpp
// Function: main
int main(int argc, char *argv[])
{
    if(argc !=4)
    {
        std::cerr << "usage: " << argv[0] << " \"pi_file.WTF\" \"file_to_compress\" \"save_path\"" << std::endl;
        std::cerr << "(" << (argc-1) << " arguments provided but exactly 3 arguments required.)" << std::endl;
        exit(EXIT_FAILURE);
    }
    const std::string pi_file=argv[1];
    const uint_fast32_t max_loop=(uint_fast32_t)std::min(uint64_t(UINT32_MAX),uint64_t(std::filesystem::file_size(pi_file)));
    if(max_loop < UINT32_MAX)
    {
        std::cerr << "Warning: pi file is small, it should be slightly larger than "<< UINT32_MAX << " bytes for better compression! (UINT32_MAX)" << std::endl;
    }
    const std::string pi_binary=file_get_contents(pi_file);
    assert(max_loop <= pi_binary.size());
    const std::string file_to_compress=argv[2];
    const size_t file_to_compress_size=std::filesystem::file_size(file_to_compress);
    std::string compress_binary=file_get_contents(file_to_compress);
    const std::string save_path=argv[3];
    if(std::filesystem::exists(save_path))
    {
        std::cerr << "Error: save file already exists! delete it first" << std::endl;
        exit(EXIT_FAILURE);
    }
    std::ofstream outfile (save_path,std::ofstream::binary);
    outfile.exceptions ( std::ofstream::failbit | std::ofstream::badbit );
    char packed[sizeof(uint32_t)+sizeof(uint8_t)];
    while(compress_binary.size()>0)
    {
        uint_fast32_t best_offset=0;
        uint_fast8_t best_offset_matches=0;
        for(uint_fast32_t pi_offset=0; pi_offset<max_loop; ++pi_offset)
        {
            uint_fast8_t matches=0;
            for(uint_fast32_t binary_offset=0; binary_offset<compress_binary.size(); ++binary_offset)
            {
                if(compress_binary[binary_offset]!=pi_binary[pi_offset+binary_offset] || matches>=UINT8_MAX)
                {
                    break;
                }
                ++matches;
            }
            if(matches>best_offset_matches)
            {
                best_offset=pi_offset;
                best_offset_matches=matches;
            }
        }
        std::cout << "offset: " << best_offset << " matches: " << uint_fast16_t(best_offset_matches) << std::endl;
        // optimized for little-endian...
        const uint32_t pack32_offset=HETOLE32(uint32_t(best_offset));
        memcpy(&packed[0],&pack32_offset,sizeof(pack32_offset));
        const uint8_t pack8_matches=uint8_t(best_offset_matches);
        memcpy(&packed[sizeof(pack32_offset)],&pack8_matches,sizeof(pack8_matches));
        outfile.write(packed, sizeof(packed));
        compress_binary.erase(0,best_offset_matches);
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x2a8, %rsp            # imm = 0x2A8
movq %rsi, %r14
cmpl $0x4, %edi
jne 0x278e
movq 0x8(%r14), %rsi
leaq 0x88(%rsp), %rbx
leaq 0xa8(%rsp), %rdx
movq %rbx, %rdi
callq 0x2a34
leaq 0xa8(%rsp), %rdi
movq %rbx, %rsi
movl $0x2, %edx
callq 0x2a72
leaq 0xa8(%rsp), %rdi
callq 0x21c0
movq %rax, %rbx
movl $0xffffffff, %r15d      # imm = 0xFFFFFFFF
cmpq %r15, %rax
cmovbq %rax, %r15
leaq 0xa8(%rsp), %rdi
callq 0x2af2
movl $0xfffffffe, %eax       # imm = 0xFFFFFFFE
cmpq %rax, %rbx
ja 0x2496
movq 0x2bbb(%rip), %rdi      # 0x4ff0
leaq 0xc37(%rip), %rsi       # 0x3073
movl $0x3d, %edx
callq 0x2190
movq 0x2ba3(%rip), %rdi      # 0x4ff0
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x20f0
movq %rax, %r12
leaq 0xc50(%rip), %rsi       # 0x30b1
movl $0x2b, %edx
movq %rax, %rdi
callq 0x2190
movq (%r12), %rax
movq -0x18(%rax), %rdi
addq %r12, %rdi
movl $0xa, %esi
callq 0x2160
movsbl %al, %esi
movq %r12, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x2100
leaq 0x68(%rsp), %rdi
leaq 0x88(%rsp), %rsi
callq 0x2951
cmpq 0x70(%rsp), %r15
ja 0x2804
movq 0x10(%r14), %rsi
leaq 0x48(%rsp), %rdi
leaq 0xa8(%rsp), %rdx
callq 0x2a34
leaq 0xa8(%rsp), %rdi
leaq 0x48(%rsp), %rsi
movl $0x2, %edx
callq 0x2a72
leaq 0xa8(%rsp), %rdi
callq 0x21c0
leaq 0xa8(%rsp), %rdi
callq 0x2af2
leaq 0x8(%rsp), %rdi
leaq 0x48(%rsp), %rsi
callq 0x2951
movq 0x18(%r14), %rsi
leaq 0x28(%rsp), %rdi
leaq 0xa8(%rsp), %rdx
callq 0x2a34
leaq 0xa8(%rsp), %rdi
leaq 0x28(%rsp), %rsi
movl $0x2, %edx
callq 0x2a72
leaq 0xa8(%rsp), %rdi
callq 0x20a0
movq %rax, %r14
leaq 0xa8(%rsp), %rdi
callq 0x2af2
testb %r14b, %r14b
je 0x2567
movzbl %r14b, %eax
cmpl $0xff, %eax
jne 0x2823
leaq 0xa8(%rsp), %rdi
leaq 0x28(%rsp), %rsi
movl $0x4, %edx
callq 0x2260
movq 0xa8(%rsp), %rax
movq -0x18(%rax), %rax
leaq (%rsp,%rax), %rdi
addq $0xa8, %rdi
movl $0x5, 0x1c(%rdi)
movl 0x20(%rdi), %esi
callq 0x2220
movq 0x10(%rsp), %rax
testq %rax, %rax
je 0x26b5
movq %rbx, %r14
testq %rbx, %rbx
je 0x2605
movq 0x8(%rsp), %rcx
movq 0x68(%rsp), %rdx
xorl %esi, %esi
xorl %ebx, %ebx
xorl %r12d, %r12d
xorl %edi, %edi
movb (%rcx,%rdi), %r8b
cmpb (%rdx,%rdi), %r8b
jne 0x25e7
cmpb $-0x1, %dil
je 0x25e7
incq %rdi
cmpq %rdi, %rax
jne 0x25cd
movl %eax, %edi
cmpb %bl, %dil
cmovaq %rsi, %r12
movzbl %dil, %edi
movzbl %bl, %ebx
cmoval %edi, %ebx
incq %rsi
incq %rdx
cmpq %r15, %rsi
jne 0x25cb
jmp 0x260a
xorl %r12d, %r12d
xorl %ebx, %ebx
movl $0x8, %edx
movq 0x29ba(%rip), %rdi      # 0x4fd0
leaq 0xb3f(%rip), %rsi       # 0x315c
callq 0x2190
movq 0x29a7(%rip), %rdi      # 0x4fd0
movq %r12, %rsi
callq 0x20f0
movq %rax, %rbp
movl $0xa, %edx
movq %rax, %rdi
leaq 0xb22(%rip), %rsi       # 0x3165
callq 0x2190
movzbl %bl, %r13d
movq %rbp, %rdi
movq %r13, %rsi
callq 0x20f0
movq %rax, %rbp
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbp, %rdi
movl $0xa, %esi
callq 0x2160
movsbl %al, %esi
movq %rbp, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x2100
movl %r12d, (%rsp)
movb %bl, 0x4(%rsp)
movl $0x5, %edx
leaq 0xa8(%rsp), %rdi
movq %rsp, %rsi
callq 0x21b0
movq %r14, %rbx
leaq 0x8(%rsp), %rdi
xorl %esi, %esi
movq %r13, %rdx
callq 0x2050
jmp 0x25a4
movq 0x2904(%rip), %rax      # 0x4fc0
movq (%rax), %rcx
movq 0x18(%rax), %rax
leaq 0xb0(%rsp), %rdi
movq %rcx, -0x8(%rdi)
movq -0x18(%rcx), %rcx
movq %rax, 0xa8(%rsp,%rcx)
callq 0x2140
leaq 0x1a0(%rsp), %rdi
callq 0x2090
leaq 0x38(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x2708
movq 0x38(%rsp), %rsi
incq %rsi
callq 0x2180
leaq 0x18(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x2723
movq 0x18(%rsp), %rsi
incq %rsi
callq 0x2180
leaq 0x58(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x273e
movq 0x58(%rsp), %rsi
incq %rsi
callq 0x2180
leaq 0x78(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x2759
movq 0x78(%rsp), %rsi
incq %rsi
callq 0x2180
leaq 0x98(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x277a
movq 0x98(%rsp), %rsi
incq %rsi
callq 0x2180
xorl %eax, %eax
addq $0x2a8, %rsp            # imm = 0x2A8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl %edi, %ebx
movq 0x2859(%rip), %r15      # 0x4ff0
leaq 0x866(%rip), %rsi       # 0x3004
movq %r15, %rdi
callq 0x2170
movq (%r14), %rsi
movq %rax, %rdi
callq 0x2170
leaq 0x854(%rip), %rsi       # 0x300c
movq %rax, %rdi
callq 0x2170
movq %rax, %rdi
callq 0x20c0
leaq 0x86b(%rip), %rsi       # 0x303a
movq %r15, %rdi
callq 0x2170
decl %ebx
movq %rax, %rdi
movl %ebx, %esi
callq 0x2230
leaq 0x852(%rip), %rsi       # 0x303c
movq %rax, %rdi
callq 0x2170
movq %rax, %rdi
callq 0x20c0
movl $0x1, %edi
callq 0x21a0
leaq 0x8d2(%rip), %rdi       # 0x30dd
leaq 0x8e8(%rip), %rsi       # 0x30fa
leaq 0x8fb(%rip), %rcx       # 0x3114
movl $0x49, %edx
callq 0x20e0
movq 0x27c6(%rip), %rdi      # 0x4ff0
leaq 0x8fa(%rip), %rsi       # 0x312b
movl $0x30, %edx
callq 0x2190
movq 0x27ae(%rip), %rdi      # 0x4ff0
callq 0x20c0
jmp 0x27fa
jmp 0x2861
jmp 0x28ac
jmp 0x2861
movq %rax, %rbx
leaq 0xa8(%rsp), %rdi
callq 0x2af2
jmp 0x28bc
movq %rax, %rbx
jmp 0x28bc
movq %rax, %rbx
jmp 0x28d7
jmp 0x287f
movq %rax, %rbx
leaq 0xa8(%rsp), %rdi
callq 0x2af2
jmp 0x28f2
movq %rax, %rbx
jmp 0x28f2
movq %rax, %rbx
jmp 0x290d
jmp 0x28a5
movq %rax, %rbx
leaq 0xa8(%rsp), %rdi
callq 0x2af2
jmp 0x2928
jmp 0x28a5
movq %rax, %rbx
jmp 0x2928
jmp 0x28ac
movq %rax, %rbx
leaq 0xa8(%rsp), %rdi
callq 0x21e0
leaq 0x38(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x28d7
movq 0x38(%rsp), %rsi
incq %rsi
callq 0x2180
leaq 0x18(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x28f2
movq 0x18(%rsp), %rsi
incq %rsi
callq 0x2180
leaq 0x58(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x290d
movq 0x58(%rsp), %rsi
incq %rsi
callq 0x2180
leaq 0x78(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x2928
movq 0x78(%rsp), %rsi
incq %rsi
callq 0x2180
leaq 0x98(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x2949
movq 0x98(%rsp), %rsi
incq %rsi
callq 0x2180
movq %rbx, %rdi
callq 0x2240