// File: divinity76[P]pi_compression/./compressor/decompressor.cpp
// Function: main
int main(int argc, char *argv[])
{
    if(argc !=4)
    {
        std::cerr << "usage: " << argv[0] << " \"pi_file.WTF\" \"file_to_decompress\" \"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_decompress=argv[2];
    const size_t file_to_decompress_size=std::filesystem::file_size(file_to_decompress);
    std::string decompress_binary=file_get_contents(file_to_decompress);
    if((decompress_binary.size()%5)!=0){
        std::cerr << "error: compressed file size must be a multiple of 5 bytes, but it's not! (" << decompress_binary.size() << " bytes)" << std::endl;
        exit(EXIT_FAILURE);
    }
    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::ifstream::failbit | std::ifstream::badbit );
    while(decompress_binary.size()>0){
        assert(decompress_binary.size()>=5);
        uint32_t sector;
        decompress_binary.copy((char*)&sector,sizeof(sector),0);
        sector=LETOHE32(sector);
        decompress_binary.erase(0,sizeof(sector));
        uint8_t length;
        decompress_binary.copy((char*)&length,sizeof(length),0);
        decompress_binary.erase(0,sizeof(length));
        outfile.write(&pi_binary[sector],length);
    }
    assert(decompress_binary.size()==0); 
}

// Assembly:
subq $0x408, %rsp            # imm = 0x408
movl $0x0, 0x404(%rsp)
movl %edi, 0x400(%rsp)
movq %rsi, 0x3f8(%rsp)
cmpl $0x4, 0x400(%rsp)
je 0x2590
movq 0x3aea(%rip), %rdi      # 0x5ff0
leaq 0x1af7(%rip), %rsi      # 0x4004
callq 0x21c0
movq %rax, %rdi
movq 0x3f8(%rsp), %rax
movq (%rax), %rsi
callq 0x21c0
movq %rax, %rdi
leaq 0x1add(%rip), %rsi      # 0x400c
callq 0x21c0
movq %rax, %rdi
movq 0x3a8a(%rip), %rsi      # 0x5fc8
callq 0x21e0
movq 0x3aa6(%rip), %rdi      # 0x5ff0
leaq 0x1bbd(%rip), %rsi      # 0x410e
callq 0x21c0
movq %rax, %rdi
movl 0x400(%rsp), %esi
subl $0x1, %esi
callq 0x2310
movq %rax, %rdi
leaq 0x1aca(%rip), %rsi      # 0x403c
callq 0x21c0
movq %rax, %rdi
movq 0x3a47(%rip), %rsi      # 0x5fc8
callq 0x21e0
movl $0x1, %edi
callq 0x2250
movq 0x3f8(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x80(%rsp)
leaq 0x3d7(%rsp), %rdi
movq %rdi, 0x88(%rsp)
callq 0x2330
movq 0x80(%rsp), %rsi
movq 0x88(%rsp), %rdx
leaq 0x3d8(%rsp), %rdi
callq 0x2da0
jmp 0x25d8
leaq 0x3d7(%rsp), %rdi
callq 0x2200
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movq %rax, 0x3b0(%rsp)
leaq 0x380(%rsp), %rdi
leaq 0x3d8(%rsp), %rsi
movl $0x2, %edx
callq 0x2ea0
jmp 0x260e
leaq 0x380(%rsp), %rdi
callq 0x2280
movq %rax, 0x78(%rsp)
jmp 0x2622
movq 0x78(%rsp), %rax
movq %rax, 0x3a8(%rsp)
leaq 0x3b0(%rsp), %rdi
leaq 0x3a8(%rsp), %rsi
callq 0x2e60
movq %rax, 0x70(%rsp)
jmp 0x264b
movq 0x70(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x68(%rsp)
leaq 0x380(%rsp), %rdi
callq 0x2fa0
movq 0x68(%rsp), %rax
movq %rax, 0x3b8(%rsp)
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
cmpq %rax, 0x3b8(%rsp)
jae 0x26e8
jmp 0x26e8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3c8(%rsp)
movl %eax, 0x3c4(%rsp)
leaq 0x3d7(%rsp), %rdi
callq 0x2200
jmp 0x2c72
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3c8(%rsp)
movl %eax, 0x3c4(%rsp)
jmp 0x2c65
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3c8(%rsp)
movl %eax, 0x3c4(%rsp)
leaq 0x380(%rsp), %rdi
callq 0x2fa0
jmp 0x2c65
leaq 0x360(%rsp), %rdi
leaq 0x3d8(%rsp), %rsi
callq 0x2c80
jmp 0x26ff
movq 0x3b8(%rsp), %rax
movq %rax, 0x60(%rsp)
leaq 0x360(%rsp), %rdi
callq 0x2160
movq %rax, %rcx
movq 0x60(%rsp), %rax
cmpq %rcx, %rax
ja 0x2728
jmp 0x2747
leaq 0x1944(%rip), %rdi      # 0x4073
leaq 0x195a(%rip), %rsi      # 0x4090
movl $0x45, %edx
leaq 0x196c(%rip), %rcx      # 0x40ae
callq 0x2140
movq 0x3f8(%rsp), %rax
movq 0x10(%rax), %rax
movq %rax, 0x50(%rsp)
leaq 0x33f(%rsp), %rdi
movq %rdi, 0x58(%rsp)
callq 0x2330
movq 0x50(%rsp), %rsi
movq 0x58(%rsp), %rdx
leaq 0x340(%rsp), %rdi
callq 0x2da0
jmp 0x2783
leaq 0x33f(%rsp), %rdi
callq 0x2200
leaq 0x308(%rsp), %rdi
leaq 0x340(%rsp), %rsi
movl $0x2, %edx
callq 0x2ea0
jmp 0x27ac
leaq 0x308(%rsp), %rdi
callq 0x2280
movq %rax, 0x48(%rsp)
jmp 0x27c0
leaq 0x308(%rsp), %rdi
callq 0x2fa0
movq 0x48(%rsp), %rax
movq %rax, 0x330(%rsp)
leaq 0x2e8(%rsp), %rdi
leaq 0x340(%rsp), %rsi
callq 0x2c80
jmp 0x27f1
leaq 0x2e8(%rsp), %rdi
callq 0x2160
movl $0x5, %ecx
xorl %edx, %edx
divq %rcx
cmpq $0x0, %rdx
je 0x2900
movq 0x37d7(%rip), %rdi      # 0x5ff0
leaq 0x18a5(%rip), %rsi      # 0x40c5
callq 0x21c0
movq %rax, 0x40(%rsp)
jmp 0x282c
leaq 0x2e8(%rsp), %rdi
callq 0x2160
movq 0x40(%rsp), %rdi
movq %rax, %rsi
callq 0x2070
movq %rax, 0x38(%rsp)
jmp 0x284d
movq 0x38(%rsp), %rdi
leaq 0x18b7(%rip), %rsi      # 0x4110
callq 0x21c0
movq %rax, 0x30(%rsp)
jmp 0x2865
movq 0x30(%rsp), %rdi
movq 0x3757(%rip), %rsi      # 0x5fc8
callq 0x21e0
jmp 0x2878
movl $0x1, %edi
callq 0x2250
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3c8(%rsp)
movl %eax, 0x3c4(%rsp)
leaq 0x33f(%rsp), %rdi
callq 0x2200
jmp 0x2c58
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3c8(%rsp)
movl %eax, 0x3c4(%rsp)
jmp 0x2c4b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3c8(%rsp)
movl %eax, 0x3c4(%rsp)
leaq 0x308(%rsp), %rdi
callq 0x2fa0
jmp 0x2c4b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3c8(%rsp)
movl %eax, 0x3c4(%rsp)
jmp 0x2c3e
movq 0x3f8(%rsp), %rax
movq 0x18(%rax), %rax
movq %rax, 0x20(%rsp)
leaq 0x2c7(%rsp), %rdi
movq %rdi, 0x28(%rsp)
callq 0x2330
movq 0x20(%rsp), %rsi
movq 0x28(%rsp), %rdx
leaq 0x2c8(%rsp), %rdi
callq 0x2da0
jmp 0x293c
leaq 0x2c7(%rsp), %rdi
callq 0x2200
leaq 0x298(%rsp), %rdi
leaq 0x2c8(%rsp), %rsi
movl $0x2, %edx
callq 0x2ea0
jmp 0x2965
leaq 0x298(%rsp), %rdi
callq 0x2fd0
movb %al, 0x1f(%rsp)
jmp 0x2978
leaq 0x298(%rsp), %rdi
callq 0x2fa0
movb 0x1f(%rsp), %al
testb $0x1, %al
jne 0x2992
jmp 0x2a2e
movq 0x3657(%rip), %rdi      # 0x5ff0
leaq 0x1778(%rip), %rsi      # 0x4118
callq 0x21c0
movq %rax, 0x10(%rsp)
jmp 0x29ac
movq 0x10(%rsp), %rdi
movq 0x3610(%rip), %rsi      # 0x5fc8
callq 0x21e0
jmp 0x29bf
movl $0x1, %edi
callq 0x2250
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3c8(%rsp)
movl %eax, 0x3c4(%rsp)
leaq 0x2c7(%rsp), %rdi
callq 0x2200
jmp 0x2c3e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3c8(%rsp)
movl %eax, 0x3c4(%rsp)
jmp 0x2c31
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3c8(%rsp)
movl %eax, 0x3c4(%rsp)
leaq 0x298(%rsp), %rdi
callq 0x2fa0
jmp 0x2c31
leaq 0x98(%rsp), %rdi
leaq 0x2c8(%rsp), %rsi
movl $0x4, %edx
callq 0x2350
jmp 0x2a4a
movq 0x98(%rsp), %rax
movq -0x18(%rax), %rax
leaq 0x98(%rsp,%rax), %rax
movq %rax, (%rsp)
movl $0x4, %edi
movl $0x1, %esi
callq 0x3000
movl %eax, 0xc(%rsp)
jmp 0x2a77
movl 0xc(%rsp), %esi
movq (%rsp), %rdi
callq 0x20d0
jmp 0x2a86
jmp 0x2a88
leaq 0x2e8(%rsp), %rdi
callq 0x2160
cmpq $0x0, %rax
jbe 0x2ba0
leaq 0x2e8(%rsp), %rdi
callq 0x2160
cmpq $0x5, %rax
jb 0x2ab4
jmp 0x2af9
leaq 0x168e(%rip), %rdi      # 0x4149
leaq 0x15ce(%rip), %rsi      # 0x4090
movl $0x56, %edx
leaq 0x15e0(%rip), %rcx      # 0x40ae
callq 0x2140
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3c8(%rsp)
movl %eax, 0x3c4(%rsp)
leaq 0x98(%rsp), %rdi
callq 0x22c0
jmp 0x2c31
xorl %eax, %eax
movl %eax, %ecx
leaq 0x2e8(%rsp), %rdi
leaq 0x94(%rsp), %rsi
movl $0x4, %edx
callq 0x2030
jmp 0x2b19
xorl %eax, %eax
movl %eax, %esi
leaq 0x2e8(%rsp), %rdi
movl $0x4, %edx
callq 0x2060
jmp 0x2b31
xorl %eax, %eax
movl %eax, %ecx
leaq 0x2e8(%rsp), %rdi
leaq 0x93(%rsp), %rsi
movl $0x1, %edx
callq 0x2030
jmp 0x2b51
xorl %eax, %eax
movl %eax, %esi
leaq 0x2e8(%rsp), %rdi
movl $0x1, %edx
callq 0x2060
jmp 0x2b69
movl 0x94(%rsp), %eax
movl %eax, %esi
leaq 0x360(%rsp), %rdi
callq 0x2230
movq %rax, %rsi
movzbl 0x93(%rsp), %eax
movl %eax, %edx
leaq 0x98(%rsp), %rdi
callq 0x2270
jmp 0x2b9b
jmp 0x2a88
leaq 0x2e8(%rsp), %rdi
callq 0x2160
cmpq $0x0, %rax
jne 0x2bb5
jmp 0x2bd4
leaq 0x15a9(%rip), %rdi      # 0x4165
leaq 0x14cd(%rip), %rsi      # 0x4090
movl $0x60, %edx
leaq 0x14df(%rip), %rcx      # 0x40ae
callq 0x2140
leaq 0x98(%rsp), %rdi
callq 0x22c0
leaq 0x2c8(%rsp), %rdi
callq 0x2130
leaq 0x2e8(%rsp), %rdi
callq 0x2130
leaq 0x340(%rsp), %rdi
callq 0x2130
leaq 0x360(%rsp), %rdi
callq 0x2130
leaq 0x3d8(%rsp), %rdi
callq 0x2130
movl 0x404(%rsp), %eax
addq $0x408, %rsp            # imm = 0x408
retq
leaq 0x2c8(%rsp), %rdi
callq 0x2130
leaq 0x2e8(%rsp), %rdi
callq 0x2130
leaq 0x340(%rsp), %rdi
callq 0x2130
leaq 0x360(%rsp), %rdi
callq 0x2130
leaq 0x3d8(%rsp), %rdi
callq 0x2130
movq 0x3c8(%rsp), %rdi
callq 0x2320
nop