// File: 2TallTim[P]modern-raytracing/raytrace.cpp
// Function: main
int main(int argc, char **argv) {
    const int nx = 960;
    const int ny = 540;
    const int ns = 1024;
    const int nobj = 500;
    const double tgt_var = 0.005;

    std::vector<hitable::Ptr> oblist;

    for (int a = -11; a < 11; a++) {
        for (int b = -11; b < 11; b++) {
            double choose_mat = rng::gen01();
            vec3 center(a + 0.9 * rng::gen01(), 0.2, b + 0.9 * rng::gen01());
            if ((center - vec3(4, 0.2, 0)).squared_length() > 0.8) {
                material::Ptr mat;
                if (choose_mat < 0.8) { //diffuse
                    mat = std::make_shared<lambert>(vec3(rng::gen01() * rng::gen01(), rng::gen01() * rng::gen01(), rng::gen01() * rng::gen01()));
                } else if (choose_mat < 0.9) { //metal
                    mat = std::make_shared<metal>(vec3(0.5 * (1 + rng::gen01()), 0.5 * (1 + rng::gen01()), 0.5 * (1 + rng::gen01())), 0.5 * rng::gen01());
                } else if (choose_mat < 0.95){
                    mat = std::make_shared<diffuse_light>(vec3(80*rng::gen01(),80*rng::gen01(),80*rng::gen01()));
                } else { //glass
                    mat = std::make_shared<dielectric>(1.5);
                }
                hitable::Ptr sp = std::make_shared<sphere>(center, 0.2, mat);
                oblist.push_back(sp);
            }
        }
    }

    material::Ptr mat = std::make_shared<lambert>(vec3(0.5, 0.5, 0.5));
    hitable::Ptr sp = std::make_shared<sphere>(vec3(0, -1000, 0), 1000, mat);
    oblist.push_back(sp);

    mat = std::make_shared<dielectric>(1.5);
    sp = std::make_shared<sphere>(vec3(0, 1, 0), 1.0, mat);
    oblist.push_back(sp);

    mat = std::make_shared<diffuse_light>(vec3(10, 10, 10));
    sp = std::make_shared<sphere>(vec3(-4, 1, 0), 1.0, mat);
    oblist.push_back(sp);

    mat = std::make_shared<metal>(vec3(0.7, 0.6, 0.5), 0.0);
    sp = std::make_shared<sphere>(vec3(4, 1, 0), 1.0, mat);
    oblist.push_back(sp);

    auto world = std::make_shared<bvh_node>(oblist.begin(), oblist.end());

    vec3 origin(12, 1, 3);
    vec3 aim(0, 1, 0);
    double dist_to_focus = (origin - aim).length();
    double aperture = 0.03;

    camera cam(origin, aim, vec3(0, 1, 0), 30, (double)nx / ny, aperture, dist_to_focus);

    std::mutex result_mutex;
    std::vector<std::string> results(ny);
    std::vector<std::string> smpmap(ny);
    std::atomic_int nextrow(-1);

    auto renderRow = [&]() -> void {
        int j = ++nextrow;
        while (j < ny){
            std::stringstream tmpresults;
            std::stringstream smpcntresults;
            tmpresults << "# ROW " << j << std::endl;
            int t_samples = 0;
            for (int i = 0; i < nx; i++){
                vec3 col, vr;

                //Intialize variance tracking
                int s = 0;
                for (s = 0; s < ns; s++) {
                    double u = (double)(i + rng::gen01()) / nx;
                    double v = (double)(j + rng::gen01()) / ny;
                    ray r = cam.get_ray(u, v);
                    vec3 sample = color(r, world);

                    t_samples++;

                    col += sample;

                    vr += vec3(sample.r() * sample.r(),
                               sample.g() * sample.g(),
                               sample.b() * sample.b());

                    if (s > sqrt((float)ns)) {
                        vec3 musquared_s((col.r() * col.r()) / s,
                                         (col.g() * col.g()) / s,
                                         (col.b() * col.b()) / s);
                        vec3 variance = ((double)s / ((s - 1) * (double)s)) * (vr - musquared_s);
                        variance = vec3(variance.r() * variance.r(),
                                        variance.g() * variance.g(),
                                        variance.b() * variance.b());
                        if ((variance.r()/(col.r()/s) < tgt_var) &&
                            (variance.g()/(col.g()/s) < tgt_var) &&
                            (variance.b()/(col.b()/s) < tgt_var)) break;
                    }
                }
                col = col / (s + 1);
                col = vec3(fmin(sqrt(col.r()),1.0), 
                           fmin(sqrt(col.g()),1.0),
                           fmin( sqrt(col.b()),1.0));
                int ir = int(255.99 * col.r());
                int ig = int(255.99 * col.g());
                int ib = int(255.99 * col.b());

                tmpresults << ir << " " << ig << " " << ib << std::endl;
                int nsgv = int((double)255.99 * ((2 * log(s) / log(ns)) - 1));
                smpcntresults << nsgv << " " << nsgv << " " << nsgv << std::endl;
            }
            std::lock_guard<std::mutex> lock(result_mutex);
            results[j] = tmpresults.str();
            smpmap[j] = smpcntresults.str();
            j = ++nextrow;
            std::cout << j << " / " << ny << " Avg samples in row: " << (double)t_samples / nx << std::endl;
        }
    };
    std::vector<std::thread> threads;
    for (int t = 0; t < std::thread::hardware_concurrency() - 1; t++) {
        threads.push_back(std::thread(renderRow));
    }
    for (auto &t : threads) {
        t.join();
    }

    std::stringstream header;
    header << "P3" << std::endl;
    header << nx << " " << ny << std::endl;
    header << "255" << std::endl;

    results.push_back(header.str());
    smpmap.push_back(header.str());
    if (argc == 1){
        for (auto iter = results.rbegin(); iter != results.rend(); iter++) {
            std::cout << *iter;
        }
    } else {
        std::ofstream out(argv[1], std::ios::out);
        for (auto iter = results.rbegin(); iter != results.rend(); iter++) {
            out << *iter;
        }
    }
    std::ofstream smpout("./samples.ppm", std::ios::out);
    for (auto iter = smpmap.rbegin(); iter != smpmap.rend(); iter++) {
        smpout << *iter;
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xd80, %rsp            # imm = 0xD80
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl $0x3c0, -0x14(%rbp)     # imm = 0x3C0
movl $0x21c, -0x18(%rbp)     # imm = 0x21C
movl $0x400, -0x1c(%rbp)     # imm = 0x400
movl $0x1f4, -0x20(%rbp)     # imm = 0x1F4
movsd 0x10533(%rip), %xmm0    # 0x17110
movsd %xmm0, -0x28(%rbp)
leaq -0x40(%rbp), %rdi
callq 0x9010
movl $0xfffffff5, -0x44(%rbp) # imm = 0xFFFFFFF5
cmpl $0xb, -0x44(%rbp)
jge 0x71a1
movl $0xfffffff5, -0x48(%rbp) # imm = 0xFFFFFFF5
cmpl $0xb, -0x48(%rbp)
jge 0x7191
callq 0x5970
movsd %xmm0, -0xb68(%rbp)
jmp 0x6c1c
movsd -0xb68(%rbp), %xmm0
movsd %xmm0, -0x50(%rbp)
cvtsi2sdl -0x44(%rbp), %xmm0
movsd %xmm0, -0xb78(%rbp)
callq 0x5970
movsd %xmm0, -0xb70(%rbp)
jmp 0x6c45
movsd -0xb78(%rbp), %xmm1
movsd -0xb70(%rbp), %xmm0
movsd 0x10503(%rip), %xmm2    # 0x17160
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0xb90(%rbp)
cvtsi2sdl -0x48(%rbp), %xmm0
movsd %xmm0, -0xb88(%rbp)
callq 0x5970
movsd %xmm0, -0xb80(%rbp)
jmp 0x6c89
movsd -0xb90(%rbp), %xmm0
movsd -0xb88(%rbp), %xmm1
movsd -0xb80(%rbp), %xmm2
movsd 0x104b7(%rip), %xmm3    # 0x17160
mulsd %xmm3, %xmm2
addsd %xmm1, %xmm2
leaq -0x78(%rbp), %rdi
movsd 0x104ab(%rip), %xmm1    # 0x17168
callq 0x3e10
jmp 0x6cc4
leaq -0xa8(%rbp), %rdi
movsd 0x10465(%rip), %xmm0    # 0x17138
movsd 0x1048d(%rip), %xmm1    # 0x17168
xorps %xmm2, %xmm2
callq 0x3e10
jmp 0x6ce5
leaq -0x90(%rbp), %rdi
leaq -0x78(%rbp), %rsi
leaq -0xa8(%rbp), %rdx
callq 0x3ba0
jmp 0x6cfe
leaq -0x90(%rbp), %rdi
callq 0x5c00
movsd %xmm0, -0xb98(%rbp)
jmp 0x6d14
movsd -0xb98(%rbp), %xmm0
movsd 0x1044c(%rip), %xmm1    # 0x17170
ucomisd %xmm1, %xmm0
jbe 0x7181
leaq -0xb8(%rbp), %rdi
callq 0x4d70
movsd 0x1042e(%rip), %xmm0    # 0x17170
ucomisd -0x50(%rbp), %xmm0
jbe 0x6e6c
callq 0x5970
movsd %xmm0, -0xba0(%rbp)
jmp 0x6d5c
callq 0x5970
movsd %xmm0, -0xba8(%rbp)
jmp 0x6d6b
movsd -0xba8(%rbp), %xmm1
movsd -0xba0(%rbp), %xmm0
mulsd %xmm1, %xmm0
movsd %xmm0, -0xbb8(%rbp)
callq 0x5970
movsd %xmm0, -0xbb0(%rbp)
jmp 0x6d96
callq 0x5970
movsd %xmm0, -0xbc0(%rbp)
jmp 0x6da5
movsd -0xbc0(%rbp), %xmm1
movsd -0xbb0(%rbp), %xmm0
mulsd %xmm1, %xmm0
movsd %xmm0, -0xbd0(%rbp)
callq 0x5970
movsd %xmm0, -0xbc8(%rbp)
jmp 0x6dd0
callq 0x5970
movsd %xmm0, -0xbd8(%rbp)
jmp 0x6ddf
movsd -0xbd0(%rbp), %xmm1
movsd -0xbb8(%rbp), %xmm0
movsd -0xbd8(%rbp), %xmm3
movsd -0xbc8(%rbp), %xmm2
mulsd %xmm3, %xmm2
leaq -0xe0(%rbp), %rdi
callq 0x3e10
jmp 0x6e11
leaq -0xc8(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
callq 0x9030
jmp 0x6e26
leaq -0xb8(%rbp), %rdi
leaq -0xc8(%rbp), %rsi
callq 0x90a0
leaq -0xc8(%rbp), %rdi
callq 0x90d0
jmp 0x70ce
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x7e24
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x7170
movsd 0x102ec(%rip), %xmm0    # 0x17160
ucomisd -0x50(%rbp), %xmm0
jbe 0x6fa5
callq 0x5970
movsd %xmm0, -0xbe0(%rbp)
jmp 0x6e8e
movsd -0xbe0(%rbp), %xmm0
movsd 0x101c2(%rip), %xmm1    # 0x17060
addsd %xmm1, %xmm0
movsd 0x10256(%rip), %xmm1    # 0x17100
mulsd %xmm1, %xmm0
movsd %xmm0, -0xbf0(%rbp)
callq 0x5970
movsd %xmm0, -0xbe8(%rbp)
jmp 0x6ec5
movsd -0xbe8(%rbp), %xmm0
movsd 0x1018b(%rip), %xmm1    # 0x17060
addsd %xmm1, %xmm0
movsd 0x1021f(%rip), %xmm1    # 0x17100
mulsd %xmm1, %xmm0
movsd %xmm0, -0xc00(%rbp)
callq 0x5970
movsd %xmm0, -0xbf8(%rbp)
jmp 0x6efc
movsd -0xc00(%rbp), %xmm1
movsd -0xbf0(%rbp), %xmm0
movsd -0xbf8(%rbp), %xmm2
movsd 0x10144(%rip), %xmm3    # 0x17060
addsd %xmm3, %xmm2
movsd 0x101d8(%rip), %xmm3    # 0x17100
mulsd %xmm3, %xmm2
leaq -0x108(%rbp), %rdi
callq 0x3e10
jmp 0x6f3a
callq 0x5970
movsd %xmm0, -0xc08(%rbp)
jmp 0x6f49
movsd -0xc08(%rbp), %xmm0
movsd 0x101a7(%rip), %xmm1    # 0x17100
mulsd %xmm1, %xmm0
movsd %xmm0, -0x110(%rbp)
leaq -0xf0(%rbp), %rdi
leaq -0x108(%rbp), %rsi
leaq -0x110(%rbp), %rdx
callq 0x90f0
jmp 0x6f81
leaq -0xb8(%rbp), %rdi
leaq -0xf0(%rbp), %rsi
callq 0x9170
leaq -0xf0(%rbp), %rdi
callq 0x91a0
jmp 0x70cc
movsd 0x101cb(%rip), %xmm0    # 0x17178
ucomisd -0x50(%rbp), %xmm0
jbe 0x7085
callq 0x5970
movsd %xmm0, -0xc10(%rbp)
jmp 0x6fc7
movsd -0xc10(%rbp), %xmm0
movsd 0x101a9(%rip), %xmm1    # 0x17180
mulsd %xmm1, %xmm0
movsd %xmm0, -0xc20(%rbp)
callq 0x5970
movsd %xmm0, -0xc18(%rbp)
jmp 0x6ff2
movsd -0xc18(%rbp), %xmm0
movsd 0x1017e(%rip), %xmm1    # 0x17180
mulsd %xmm1, %xmm0
movsd %xmm0, -0xc30(%rbp)
callq 0x5970
movsd %xmm0, -0xc28(%rbp)
jmp 0x701d
movsd -0xc30(%rbp), %xmm1
movsd -0xc20(%rbp), %xmm0
movsd -0xc28(%rbp), %xmm2
movsd 0x10143(%rip), %xmm3    # 0x17180
mulsd %xmm3, %xmm2
leaq -0x138(%rbp), %rdi
callq 0x3e10
jmp 0x704f
leaq -0x120(%rbp), %rdi
leaq -0x138(%rbp), %rsi
callq 0x91c0
jmp 0x7064
leaq -0xb8(%rbp), %rdi
leaq -0x120(%rbp), %rsi
callq 0x9230
leaq -0x120(%rbp), %rdi
callq 0x9260
jmp 0x70ca
movabsq $0x3ff8000000000000, %rax # imm = 0x3FF8000000000000
movq %rax, -0x150(%rbp)
leaq -0x148(%rbp), %rdi
leaq -0x150(%rbp), %rsi
callq 0x9280
jmp 0x70ab
leaq -0xb8(%rbp), %rdi
leaq -0x148(%rbp), %rsi
callq 0x92f0
leaq -0x148(%rbp), %rdi
callq 0x9320
jmp 0x70cc
jmp 0x70ce
movabsq $0x3fc999999999999a, %rax # imm = 0x3FC999999999999A
movq %rax, -0x178(%rbp)
leaq -0x170(%rbp), %rdi
leaq -0x78(%rbp), %rsi
leaq -0x178(%rbp), %rdx
leaq -0xb8(%rbp), %rcx
callq 0x9340
jmp 0x70ff
leaq -0x160(%rbp), %rdi
movq %rdi, -0xc38(%rbp)
leaq -0x170(%rbp), %rsi
movq %rsi, -0xc40(%rbp)
callq 0x93c0
movq -0xc40(%rbp), %rdi
callq 0x93f0
movq -0xc38(%rbp), %rsi
leaq -0x40(%rbp), %rdi
callq 0x4800
jmp 0x713e
leaq -0x160(%rbp), %rdi
callq 0x47a0
leaq -0xb8(%rbp), %rdi
callq 0x4ec0
jmp 0x7181
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x160(%rbp), %rdi
callq 0x47a0
leaq -0xb8(%rbp), %rdi
callq 0x4ec0
jmp 0x7e24
jmp 0x7183
movl -0x48(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x48(%rbp)
jmp 0x6c03
jmp 0x7193
movl -0x44(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x44(%rbp)
jmp 0x6bf2
leaq -0x1b0(%rbp), %rdi
movsd 0xff50(%rip), %xmm2     # 0x17100
movaps %xmm2, %xmm0
movaps %xmm2, %xmm1
callq 0x3e10
jmp 0x71bd
leaq -0x198(%rbp), %rdi
leaq -0x1b0(%rbp), %rsi
callq 0x9030
jmp 0x71d2
leaq -0x188(%rbp), %rdi
leaq -0x198(%rbp), %rsi
movq %rsi, -0xc48(%rbp)
callq 0x9410
movq -0xc48(%rbp), %rdi
callq 0x90d0
leaq -0x1e8(%rbp), %rdi
movsd 0xff11(%rip), %xmm1     # 0x17118
xorps %xmm2, %xmm2
movaps %xmm2, %xmm0
callq 0x3e10
jmp 0x7214
movl $0x3e8, -0x1ec(%rbp)    # imm = 0x3E8
leaq -0x1d0(%rbp), %rdi
leaq -0x1e8(%rbp), %rsi
leaq -0x1ec(%rbp), %rdx
leaq -0x188(%rbp), %rcx
callq 0x9440
jmp 0x7241
leaq -0x1c0(%rbp), %rdi
movq %rdi, -0xc50(%rbp)
leaq -0x1d0(%rbp), %rsi
movq %rsi, -0xc58(%rbp)
callq 0x93c0
movq -0xc58(%rbp), %rdi
callq 0x93f0
movq -0xc50(%rbp), %rsi
leaq -0x40(%rbp), %rdi
callq 0x4800
jmp 0x7280
movabsq $0x3ff8000000000000, %rax # imm = 0x3FF8000000000000
movq %rax, -0x208(%rbp)
leaq -0x200(%rbp), %rdi
leaq -0x208(%rbp), %rsi
callq 0x9280
jmp 0x72a6
leaq -0x188(%rbp), %rdi
leaq -0x200(%rbp), %rsi
movq %rsi, -0xc60(%rbp)
callq 0x92f0
movq -0xc60(%rbp), %rdi
callq 0x9320
leaq -0x230(%rbp), %rdi
movsd 0xfd85(%rip), %xmm1     # 0x17060
xorps %xmm2, %xmm2
movaps %xmm2, %xmm0
callq 0x3e10
jmp 0x72e8
movabsq $0x3ff0000000000000, %rax # imm = 0x3FF0000000000000
movq %rax, -0x238(%rbp)
leaq -0x218(%rbp), %rdi
leaq -0x230(%rbp), %rsi
leaq -0x238(%rbp), %rdx
leaq -0x188(%rbp), %rcx
callq 0x94c0
jmp 0x731c
leaq -0x1c0(%rbp), %rdi
movq %rdi, -0xc68(%rbp)
leaq -0x218(%rbp), %rsi
movq %rsi, -0xc70(%rbp)
callq 0x9540
movq -0xc70(%rbp), %rdi
callq 0x93f0
movq -0xc68(%rbp), %rsi
leaq -0x40(%rbp), %rdi
callq 0x4800
jmp 0x735b
leaq -0x260(%rbp), %rdi
movsd 0xfdb6(%rip), %xmm2     # 0x17120
movaps %xmm2, %xmm0
movaps %xmm2, %xmm1
callq 0x3e10
jmp 0x7377
leaq -0x248(%rbp), %rdi
leaq -0x260(%rbp), %rsi
callq 0x91c0
jmp 0x738c
leaq -0x188(%rbp), %rdi
leaq -0x248(%rbp), %rsi
movq %rsi, -0xc78(%rbp)
callq 0x9230
movq -0xc78(%rbp), %rdi
callq 0x9260
leaq -0x288(%rbp), %rdi
movsd 0xfd67(%rip), %xmm0     # 0x17128
movsd 0xfc97(%rip), %xmm1     # 0x17060
xorps %xmm2, %xmm2
callq 0x3e10
jmp 0x73d3
movabsq $0x3ff0000000000000, %rax # imm = 0x3FF0000000000000
movq %rax, -0x290(%rbp)
leaq -0x270(%rbp), %rdi
leaq -0x288(%rbp), %rsi
leaq -0x290(%rbp), %rdx
leaq -0x188(%rbp), %rcx
callq 0x94c0
jmp 0x7407
leaq -0x1c0(%rbp), %rdi
movq %rdi, -0xc80(%rbp)
leaq -0x270(%rbp), %rsi
movq %rsi, -0xc88(%rbp)
callq 0x9540
movq -0xc88(%rbp), %rdi
callq 0x93f0
movq -0xc80(%rbp), %rsi
leaq -0x40(%rbp), %rdi
callq 0x4800
jmp 0x7446
leaq -0x2b8(%rbp), %rdi
movsd 0xfcb3(%rip), %xmm0     # 0x17108
movsd 0xfcd3(%rip), %xmm1     # 0x17130
movsd 0xfc9b(%rip), %xmm2     # 0x17100
callq 0x3e10
jmp 0x746c
movq $0x0, -0x2c0(%rbp)
leaq -0x2a0(%rbp), %rdi
leaq -0x2b8(%rbp), %rsi
leaq -0x2c0(%rbp), %rdx
callq 0x90f0
jmp 0x7493
leaq -0x188(%rbp), %rdi
leaq -0x2a0(%rbp), %rsi
movq %rsi, -0xc90(%rbp)
callq 0x9170
movq -0xc90(%rbp), %rdi
callq 0x91a0
leaq -0x2e8(%rbp), %rdi
movsd 0xfc70(%rip), %xmm0     # 0x17138
movsd 0xfb90(%rip), %xmm1     # 0x17060
xorps %xmm2, %xmm2
callq 0x3e10
jmp 0x74da
movabsq $0x3ff0000000000000, %rax # imm = 0x3FF0000000000000
movq %rax, -0x2f0(%rbp)
leaq -0x2d0(%rbp), %rdi
leaq -0x2e8(%rbp), %rsi
leaq -0x2f0(%rbp), %rdx
leaq -0x188(%rbp), %rcx
callq 0x94c0
jmp 0x750e
leaq -0x1c0(%rbp), %rdi
movq %rdi, -0xc98(%rbp)
leaq -0x2d0(%rbp), %rsi
movq %rsi, -0xca0(%rbp)
callq 0x9540
movq -0xca0(%rbp), %rdi
callq 0x93f0
movq -0xc98(%rbp), %rsi
leaq -0x40(%rbp), %rdi
callq 0x4800
jmp 0x754d
leaq -0x40(%rbp), %rdi
movq %rdi, -0xca8(%rbp)
callq 0x48f0
movq -0xca8(%rbp), %rdi
movq %rax, -0x308(%rbp)
callq 0x4980
movq %rax, -0x310(%rbp)
leaq -0x300(%rbp), %rdi
leaq -0x308(%rbp), %rsi
leaq -0x310(%rbp), %rdx
callq 0x9570
jmp 0x7593
leaq -0x328(%rbp), %rdi
movsd 0xfb9e(%rip), %xmm0     # 0x17140
movsd 0xfab6(%rip), %xmm1     # 0x17060
movsd 0xfb96(%rip), %xmm2     # 0x17148
callq 0x3e10
jmp 0x75b9
leaq -0x340(%rbp), %rdi
movsd 0xfa98(%rip), %xmm1     # 0x17060
xorps %xmm2, %xmm2
movaps %xmm2, %xmm0
callq 0x3e10
jmp 0x75d5
leaq -0x360(%rbp), %rdi
leaq -0x328(%rbp), %rsi
leaq -0x340(%rbp), %rdx
callq 0x3ba0
jmp 0x75f1
leaq -0x360(%rbp), %rdi
callq 0x95f0
movsd %xmm0, -0xcb0(%rbp)
jmp 0x7607
movsd -0xcb0(%rbp), %xmm0
movsd %xmm0, -0x348(%rbp)
movabsq $0x3f9eb851eb851eb8, %rax # imm = 0x3F9EB851EB851EB8
movq %rax, -0x368(%rbp)
movq -0x318(%rbp), %rax
movq %rax, -0x420(%rbp)
movups -0x328(%rbp), %xmm0
movaps %xmm0, -0x430(%rbp)
movq -0x330(%rbp), %rax
movq %rax, -0x440(%rbp)
movups -0x340(%rbp), %xmm0
movaps %xmm0, -0x450(%rbp)
leaq -0x468(%rbp), %rdi
movsd 0xf9f1(%rip), %xmm1     # 0x17060
xorps %xmm2, %xmm2
movaps %xmm2, %xmm0
callq 0x3e10
jmp 0x767c
movsd -0x368(%rbp), %xmm2
movsd -0x348(%rbp), %xmm3
movq -0x458(%rbp), %rcx
movq %rsp, %rax
movq %rcx, 0x40(%rax)
movups -0x468(%rbp), %xmm0
movups %xmm0, 0x30(%rax)
movq -0x440(%rbp), %rcx
movq %rcx, 0x28(%rax)
movaps -0x450(%rbp), %xmm0
movups %xmm0, 0x18(%rax)
movq -0x420(%rbp), %rcx
movq %rcx, 0x10(%rax)
movaps -0x430(%rbp), %xmm0
movups %xmm0, (%rax)
leaq -0x418(%rbp), %rdi
movsd 0xfa71(%rip), %xmm0     # 0x17150
movsd 0xfa71(%rip), %xmm1     # 0x17158
callq 0x9610
jmp 0x76ee
leaq -0x490(%rbp), %rdi
callq 0x9910
leaq -0x4a9(%rbp), %rdi
movq %rdi, -0xcb8(%rbp)
callq 0x9930
movq -0xcb8(%rbp), %rdx
leaq -0x4a8(%rbp), %rdi
movl $0x21c, %esi            # imm = 0x21C
callq 0x9950
jmp 0x7727
leaq -0x4a9(%rbp), %rdi
callq 0x99c0
leaq -0x4c9(%rbp), %rdi
movq %rdi, -0xcc0(%rbp)
callq 0x9930
movq -0xcc0(%rbp), %rdx
leaq -0x4c8(%rbp), %rdi
movl $0x21c, %esi            # imm = 0x21C
callq 0x9950
jmp 0x7760
leaq -0x4c9(%rbp), %rdi
callq 0x99c0
movl 0xfa4a(%rip), %eax      # 0x171bc
movl %eax, -0x4d0(%rbp)
leaq -0x4d0(%rbp), %rax
movq %rax, -0x508(%rbp)
leaq -0x418(%rbp), %rax
movq %rax, -0x500(%rbp)
leaq -0x300(%rbp), %rax
movq %rax, -0x4f8(%rbp)
leaq -0x28(%rbp), %rax
movq %rax, -0x4f0(%rbp)
leaq -0x490(%rbp), %rax
movq %rax, -0x4e8(%rbp)
leaq -0x4a8(%rbp), %rax
movq %rax, -0x4e0(%rbp)
leaq -0x4c8(%rbp), %rax
movq %rax, -0x4d8(%rbp)
leaq -0x520(%rbp), %rdi
callq 0x99e0
movl $0x0, -0x524(%rbp)
movl -0x524(%rbp), %eax
movl %eax, -0xcc4(%rbp)
callq 0x32c0
movl %eax, %ecx
movl -0xcc4(%rbp), %eax
subl $0x1, %ecx
cmpl %ecx, %eax
jae 0x78f3
leaq -0x530(%rbp), %rdi
leaq -0x508(%rbp), %rsi
callq 0x7e40
jmp 0x7826
leaq -0x520(%rbp), %rdi
leaq -0x530(%rbp), %rsi
callq 0x9a00
jmp 0x783b
leaq -0x530(%rbp), %rdi
callq 0x9a30
movl -0x524(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x524(%rbp)
jmp 0x77ed
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x7e18
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x7e0c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x7e00
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x4a9(%rbp), %rdi
callq 0x99c0
jmp 0x7e00
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x4c9(%rbp), %rdi
callq 0x99c0
jmp 0x7df4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x7ddc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x530(%rbp), %rdi
callq 0x9a30
jmp 0x7ddc
leaq -0x520(%rbp), %rax
movq %rax, -0x538(%rbp)
movq -0x538(%rbp), %rdi
callq 0x9a60
movq %rax, -0x540(%rbp)
movq -0x538(%rbp), %rdi
callq 0x9a90
movq %rax, -0x548(%rbp)
leaq -0x540(%rbp), %rdi
leaq -0x548(%rbp), %rsi
callq 0x9ac0
testb $0x1, %al
jne 0x7940
jmp 0x7971
leaq -0x540(%rbp), %rdi
callq 0x9b00
movq %rax, -0x550(%rbp)
movq -0x550(%rbp), %rdi
callq 0x3360
jmp 0x7961
jmp 0x7963
leaq -0x540(%rbp), %rdi
callq 0x9b20
jmp 0x7927
leaq -0x6d8(%rbp), %rdi
callq 0x3110
jmp 0x797f
leaq -0x6c8(%rbp), %rdi
leaq 0xf833(%rip), %rsi      # 0x171c0
callq 0x3210
movq %rax, -0xcd0(%rbp)
jmp 0x799b
movq -0xcd0(%rbp), %rdi
movq 0x1a607(%rip), %rsi     # 0x21fb0
callq 0x3240
jmp 0x79b0
leaq -0x6c8(%rbp), %rdi
movl $0x3c0, %esi            # imm = 0x3C0
callq 0x3370
movq %rax, -0xcd8(%rbp)
jmp 0x79ca
movq -0xcd8(%rbp), %rdi
leaq 0xf837(%rip), %rsi      # 0x1720f
callq 0x3210
movq %rax, -0xce0(%rbp)
jmp 0x79e6
movq -0xce0(%rbp), %rdi
movl $0x21c, %esi            # imm = 0x21C
callq 0x3370
movq %rax, -0xce8(%rbp)
jmp 0x7a00
movq -0xce8(%rbp), %rdi
movq 0x1a5a2(%rip), %rsi     # 0x21fb0
callq 0x3240
jmp 0x7a15
leaq -0x6c8(%rbp), %rdi
leaq 0xf7a0(%rip), %rsi      # 0x171c3
callq 0x3210
movq %rax, -0xcf0(%rbp)
jmp 0x7a31
movq -0xcf0(%rbp), %rdi
movq 0x1a571(%rip), %rsi     # 0x21fb0
callq 0x3240
jmp 0x7a46
leaq -0x6f8(%rbp), %rdi
leaq -0x6d8(%rbp), %rsi
callq 0x3200
jmp 0x7a5b
leaq -0x4a8(%rbp), %rdi
leaq -0x6f8(%rbp), %rsi
callq 0x9b40
jmp 0x7a70
leaq -0x6f8(%rbp), %rdi
callq 0x30e0
leaq -0x718(%rbp), %rdi
leaq -0x6d8(%rbp), %rsi
callq 0x3200
jmp 0x7a91
leaq -0x4c8(%rbp), %rdi
leaq -0x718(%rbp), %rsi
callq 0x9b40
jmp 0x7aa6
leaq -0x718(%rbp), %rdi
callq 0x30e0
cmpl $0x1, -0x8(%rbp)
jne 0x7bab
leaq -0x720(%rbp), %rdi
leaq -0x4a8(%rbp), %rsi
callq 0x9b70
leaq -0x728(%rbp), %rdi
movq %rdi, -0xd00(%rbp)
leaq -0x4a8(%rbp), %rsi
callq 0x9bf0
movq -0xd00(%rbp), %rsi
leaq -0x720(%rbp), %rdi
callq 0x9bc0
movb %al, -0xcf1(%rbp)
jmp 0x7b04
movb -0xcf1(%rbp), %al
testb $0x1, %al
jne 0x7b13
jmp 0x7ba6
leaq -0x720(%rbp), %rdi
callq 0x9c40
movq %rax, -0xd08(%rbp)
jmp 0x7b28
movq -0xd08(%rbp), %rsi
movq 0x1a49a(%rip), %rdi     # 0x21fd0
callq 0x31d0
jmp 0x7b3d
jmp 0x7b3f
leaq -0x730(%rbp), %rdi
leaq -0x720(%rbp), %rsi
xorl %edx, %edx
callq 0x9c70
jmp 0x7b56
jmp 0x7acf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x7dd0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x6f8(%rbp), %rdi
callq 0x30e0
jmp 0x7dd0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x718(%rbp), %rdi
callq 0x30e0
jmp 0x7dd0
jmp 0x7c8b
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rsi
leaq -0x930(%rbp), %rdi
movl $0x10, %edx
callq 0x3270
jmp 0x7bc6
leaq -0x938(%rbp), %rdi
leaq -0x4a8(%rbp), %rsi
callq 0x9b70
leaq -0x940(%rbp), %rdi
movq %rdi, -0xd18(%rbp)
leaq -0x4a8(%rbp), %rsi
callq 0x9bf0
movq -0xd18(%rbp), %rsi
leaq -0x938(%rbp), %rdi
callq 0x9bc0
movb %al, -0xd09(%rbp)
jmp 0x7c0e
movb -0xd09(%rbp), %al
testb $0x1, %al
jne 0x7c1a
jmp 0x7c7f
leaq -0x938(%rbp), %rdi
callq 0x9c40
movq %rax, -0xd20(%rbp)
jmp 0x7c2f
movq -0xd20(%rbp), %rsi
leaq -0x930(%rbp), %rdi
callq 0x31d0
jmp 0x7c44
jmp 0x7c46
leaq -0x948(%rbp), %rdi
leaq -0x938(%rbp), %rsi
xorl %edx, %edx
callq 0x9c70
jmp 0x7c5d
jmp 0x7bd9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x930(%rbp), %rdi
callq 0x3320
jmp 0x7dd0
leaq -0x930(%rbp), %rdi
callq 0x3320
leaq 0xf535(%rip), %rsi      # 0x171c7
leaq -0xb48(%rbp), %rdi
movl $0x10, %edx
callq 0x3270
jmp 0x7ca5
leaq -0xb50(%rbp), %rdi
leaq -0x4c8(%rbp), %rsi
callq 0x9b70
leaq -0xb58(%rbp), %rdi
movq %rdi, -0xd30(%rbp)
leaq -0x4c8(%rbp), %rsi
callq 0x9bf0
movq -0xd30(%rbp), %rsi
leaq -0xb50(%rbp), %rdi
callq 0x9bc0
movb %al, -0xd21(%rbp)
jmp 0x7ced
movb -0xd21(%rbp), %al
testb $0x1, %al
jne 0x7cf9
jmp 0x7d5b
leaq -0xb50(%rbp), %rdi
callq 0x9c40
movq %rax, -0xd38(%rbp)
jmp 0x7d0e
movq -0xd38(%rbp), %rsi
leaq -0xb48(%rbp), %rdi
callq 0x31d0
jmp 0x7d23
jmp 0x7d25
leaq -0xb60(%rbp), %rdi
leaq -0xb50(%rbp), %rsi
xorl %edx, %edx
callq 0x9c70
jmp 0x7d3c
jmp 0x7cb8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0xb48(%rbp), %rdi
callq 0x3320
jmp 0x7dd0
leaq -0xb48(%rbp), %rdi
callq 0x3320
leaq -0x6d8(%rbp), %rdi
callq 0x3140
leaq -0x520(%rbp), %rdi
callq 0x9cb0
leaq -0x4c8(%rbp), %rdi
callq 0x9d10
leaq -0x4a8(%rbp), %rdi
callq 0x9d10
leaq -0x300(%rbp), %rdi
callq 0x9d70
leaq -0x1c0(%rbp), %rdi
callq 0x47a0
leaq -0x188(%rbp), %rdi
callq 0x4ec0
leaq -0x40(%rbp), %rdi
callq 0x9d90
movl -0x4(%rbp), %eax
addq $0xd80, %rsp            # imm = 0xD80
popq %rbp
retq
leaq -0x6d8(%rbp), %rdi
callq 0x3140
leaq -0x520(%rbp), %rdi
callq 0x9cb0
leaq -0x4c8(%rbp), %rdi
callq 0x9d10
leaq -0x4a8(%rbp), %rdi
callq 0x9d10
leaq -0x300(%rbp), %rdi
callq 0x9d70
leaq -0x1c0(%rbp), %rdi
callq 0x47a0
leaq -0x188(%rbp), %rdi
callq 0x4ec0
leaq -0x40(%rbp), %rdi
callq 0x9d90
movq -0x58(%rbp), %rdi
callq 0x3390
nopw %cs:(%rax,%rax)