// File: /workspace/github_cpp_makefile_star2_O2/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, %rbx
cmpl $0x4, %edi
jne 0x2624
movq 0x8(%rbx), %rsi
leaq 0x88(%rsp), %r14
leaq 0xa8(%rsp), %rdx
movq %r14, %rdi
callq 0x282a
leaq 0xa8(%rsp), %rdi
pushq $0x2
popq %rdx
movq %r14, %rsi
callq 0x2866
leaq 0xa8(%rsp), %rdi
callq 0x2170
movq %rax, %r14
movl $0xffffffff, %r12d      # imm = 0xFFFFFFFF
cmpq %r12, %rax
cmovbq %rax, %r12
leaq 0xa8(%rsp), %rdi
callq 0x28ce
movl $0xfffffffe, %eax       # imm = 0xFFFFFFFE
cmpq %rax, %r14
ja 0x2403
movq 0x2c1d(%rip), %rdi      # 0x4ff0
leaq 0xc99(%rip), %rsi       # 0x3073
callq 0x2140
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movq %rax, %rdi
callq 0x20f0
leaq 0xcbe(%rip), %rsi       # 0x30b1
movq %rax, %rdi
callq 0x2140
movq %rax, %rdi
callq 0x20d0
leaq 0x68(%rsp), %rdi
leaq 0x88(%rsp), %rsi
callq 0x277c
cmpq 0x70(%rsp), %r12
ja 0x2698
movq 0x10(%rbx), %rsi
leaq 0x48(%rsp), %rdi
leaq 0xa8(%rsp), %rdx
callq 0x282a
leaq 0xa8(%rsp), %rdi
leaq 0x48(%rsp), %rsi
pushq $0x2
popq %rdx
callq 0x2866
leaq 0xa8(%rsp), %rdi
callq 0x2170
leaq 0xa8(%rsp), %rdi
callq 0x28ce
leaq 0x8(%rsp), %rdi
leaq 0x48(%rsp), %rsi
callq 0x277c
movq 0x18(%rbx), %rsi
leaq 0x28(%rsp), %rdi
leaq 0xa8(%rsp), %rdx
callq 0x282a
leaq 0xa8(%rsp), %rdi
leaq 0x28(%rsp), %rsi
pushq $0x2
popq %rdx
callq 0x2866
leaq 0xa8(%rsp), %rdi
callq 0x28e4
movl %eax, %ebx
leaq 0xa8(%rsp), %rdi
callq 0x28ce
testb %bl, %bl
jne 0x26b5
leaq 0xa8(%rsp), %rbx
leaq 0x28(%rsp), %rsi
pushq $0x4
popq %rdx
movq %rbx, %rdi
callq 0x2200
movq 0xa8(%rsp), %rax
addq -0x18(%rax), %rbx
pushq $0x5
popq %rsi
movq %rbx, %rdi
callq 0x2090
pushq $0x5
popq %rbp
leaq 0x8(%rsp), %rbx
movq 0x10(%rsp), %rax
testq %rax, %rax
je 0x25ce
movq 0x8(%rsp), %rcx
movq 0x68(%rsp), %rdx
xorl %r14d, %r14d
xorl %r13d, %r13d
xorl %esi, %esi
movzbl %r13b, %r15d
cmpq %r12, %rsi
je 0x2560
xorl %r8d, %r8d
cmpq %r8, %rax
je 0x2547
movb (%rcx,%r8), %r9b
leaq 0x1(%r8), %rdi
cmpb (%rdx,%r8), %r9b
jne 0x2542
cmpb $-0x1, %r8b
movq %rdi, %r8
jne 0x2526
decb %dil
jmp 0x2549
movl %eax, %edi
cmpb %r15b, %dil
cmovaq %rsi, %r14
movzbl %dil, %r13d
cmovbel %r15d, %r13d
incq %rsi
incq %rdx
jmp 0x251a
movq 0x2a69(%rip), %rdi      # 0x4fd0
leaq 0xbee(%rip), %rsi       # 0x315c
callq 0x2140
movq %rax, %rdi
movq %r14, %rsi
callq 0x20f0
movq %rax, %rdi
leaq 0xbdd(%rip), %rsi       # 0x3165
callq 0x2140
movq %rax, %rdi
movq %r15, %rsi
callq 0x20f0
movq %rax, %rdi
callq 0x20d0
movl %r14d, (%rsp)
movb %r13b, 0x4(%rsp)
leaq 0xa8(%rsp), %rdi
movq %rsp, %rsi
movq %rbp, %rdx
callq 0x2160
movq %rbx, %rdi
xorl %esi, %esi
movq %r15, %rdx
callq 0x2040
jmp 0x24fa
leaq 0xa8(%rsp), %rdi
callq 0x2190
leaq 0x28(%rsp), %rdi
callq 0x20c0
leaq 0x8(%rsp), %rdi
callq 0x20c0
leaq 0x48(%rsp), %rdi
callq 0x20c0
leaq 0x68(%rsp), %rdi
callq 0x20c0
leaq 0x88(%rsp), %rdi
callq 0x20c0
xorl %eax, %eax
addq $0x2a8, %rsp            # imm = 0x2A8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl %edi, %ebp
movq 0x29c3(%rip), %r14      # 0x4ff0
leaq 0x9d0(%rip), %rsi       # 0x3004
movq %r14, %rdi
callq 0x2140
movq (%rbx), %rsi
movq %rax, %rdi
callq 0x2140
leaq 0x9be(%rip), %rsi       # 0x300c
movq %rax, %rdi
callq 0x2140
movq %rax, %rdi
callq 0x20d0
leaq 0x9d5(%rip), %rsi       # 0x303a
movq %r14, %rdi
callq 0x2140
decl %ebp
movq %rax, %rdi
movl %ebp, %esi
callq 0x21d0
leaq 0x9bc(%rip), %rsi       # 0x303c
movq %rax, %rdi
callq 0x2140
movq %rax, %rdi
callq 0x20d0
pushq $0x1
popq %rdi
callq 0x2150
leaq 0xa3e(%rip), %rdi       # 0x30dd
leaq 0xa54(%rip), %rsi       # 0x30fa
leaq 0xa67(%rip), %rcx       # 0x3114
pushq $0x49
popq %rdx
callq 0x20e0
movq 0x2934(%rip), %rdi      # 0x4ff0
leaq 0xa68(%rip), %rsi       # 0x312b
callq 0x2140
movq %rax, %rdi
callq 0x20d0
jmp 0x2690
jmp 0x26ea
jmp 0x272f
jmp 0x26ea
movq %rax, %rbx
leaq 0xa8(%rsp), %rdi
callq 0x28ce
jmp 0x273f
movq %rax, %rbx
jmp 0x273f
movq %rax, %rbx
jmp 0x2749
jmp 0x2708
movq %rax, %rbx
leaq 0xa8(%rsp), %rdi
callq 0x28ce
jmp 0x2753
movq %rax, %rbx
jmp 0x2753
movq %rax, %rbx
jmp 0x275d
jmp 0x2728
movq %rax, %rbx
leaq 0xa8(%rsp), %rdi
callq 0x28ce
jmp 0x2767
jmp 0x2728
movq %rax, %rbx
jmp 0x2767
jmp 0x272f
movq %rax, %rbx
leaq 0xa8(%rsp), %rdi
callq 0x2190
leaq 0x28(%rsp), %rdi
callq 0x20c0
leaq 0x8(%rsp), %rdi
callq 0x20c0
leaq 0x48(%rsp), %rdi
callq 0x20c0
leaq 0x68(%rsp), %rdi
callq 0x20c0
leaq 0x88(%rsp), %rdi
callq 0x20c0
movq %rbx, %rdi
callq 0x21e0