// File: khedoros[P]khednes/main.cpp
// Function: main
int main(int argc, char ** argv) {
    opterr = 0;
    char option;
    int res=1;
    int mapper=0;
    //cout<<"Argc: "<<argc<<endl;
    if(argc==1) {
        cout<<"Usage:\n\n./"<<argv[0]<<" [-d #] [-m #] <filename>\n\n\tOptions:\n\t-d Enables debug output. Options for # are:\n\t\t1\tCPU\n\t\t2\tMAIN\n\t\t3\tMEM\n\t\t4\tPPU\n\t\t5\tROM\n\t\t6\tUTIL\n\t\t7\tWAV\n\t\t7\tAPU\n";
        cout<<"\n\t-m manually specifies an iNES mapper number to use.\n";
    }

    while(argc>3&&(option=getopt(argc,argv,"d:x:m:"))!=-1) {
        switch(option) {
        case 'd':
            util::toggle_log(atoi(optarg));
            break;
        case 'x':
            res=atoi(optarg);
            break;
        case 'm':
            mapper=atoi(optarg);
            break;
        default:
            cerr<<"Unkown option '"<<optopt<<".\n";
            return 1;
        }
    }
    if(res==0)
        res=1; 
    std::string filename;
    if(optind<argc||argc==2) {
        filename=std::string(argv[optind]);
        cout<<"Loading "<<filename<<"..."<<endl;
    }
    else {
        cout<<"Give a single filename, like this: \n\n\t"<<argv[0]<<" rom.nes"<<endl;        
        return 1;
    }
        
//        if( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO) < 0 ) {
    bool headless = false;
    if( SDL_Init(SDL_INIT_EVERYTHING|SDL_INIT_JOYSTICK|SDL_INIT_GAMECONTROLLER|SDL_INIT_NOPARACHUTE) < 0 ) {
        if( SDL_Init(SDL_INIT_NOPARACHUTE|SDL_INIT_AUDIO) < 0) {
            fprintf(stderr,"Couldn't initialize SDL: %s\n", SDL_GetError());
            exit(1);
        }
        headless = true;
        cout<<"Running in headless mode due to difficulty initializing some SDL subsystems."<<endl;
    }

    //cout<<"Trying to open the joystick (if any)"<<endl;

    SDL_Joystick * js = NULL;
    int jscount = SDL_NumJoysticks();
    if(jscount > 0) {
        for(int i=0;i<jscount;++i) {
            const char * name = SDL_JoystickNameForIndex(i);
            cout<<"Found joystick: "<<name<<endl;
        }
        cout<<"Just opening joystick 0 though"<<endl;
        js = SDL_JoystickOpen(0);
    }

    //cout<<"Done with joystick stuff"<<endl;

    //cout<<"Going to load cartridge"<<endl;
    rom cart(filename, mapper);
    //cout<<"Cart loaded. Going to start ppu"<<endl;
    ppu ppui(cart,res);
    //cout<<"PPU started. Going to start apu."<<endl;
    if(ppui.dummy) {
        headless = true;
        cout<<"PPU started in dummy mode, so audio will too."<<endl;
    }
    apu apui(headless);
    SDL_PauseAudioDevice(apui.get_id(), true);
    //cout<<"APU started. Going to bring up memory map"<<endl;
    mem memi(cart,ppui,apui);
    apui.setmem(&memi);
    //cout<<"Memory started. Going to start CPU"<<endl;
    cpu cpui(&memi,&apui,memi.get_rst_addr(), cart.isNSF());
    //cout<<"CPU started."<<endl;

    if(cart.isNSF()) {
        cout<<"Starting NSF player instead of main emulator"<<endl;
        return run_nsf(cart, apui, memi, cpui);
    }

    bool paused=false;
    //int time_stop;
    //long total_time;
    int pstart = SDL_GetTicks();
    //int delay = 0;
    //long delay_count = 0;
    //long delay_total = 0;
    SDL_PauseAudioDevice(apui.get_id(), false);
    while (1==1) {
        //cout<<"Start of event loop."<<endl;
        //int frame_start = SDL_GetTicks();
        SDL_Event event;
        //int curx,cury;
        int newx,newy;
        //bool changed;
        //cout<<"Polling and handling events"<<endl;
        while(SDL_PollEvent(&event)){  /* Loop until there are no events left on the queue */
            switch(event.type){  /* Process the appropiate event type */
            case SDL_JOYBUTTONDOWN:
            case SDL_JOYBUTTONUP:
                {
                SDL_Scancode sc;
                int button = int(event.jbutton.button);
                int state = int(event.jbutton.state);
                //cout<<"Button: "<<state<<" state: "<<state<<endl;
                cout<<"Saw button: "<<button<<endl;
                switch(button) {
                case 0: sc = SDL_SCANCODE_L; break;
                case 1: sc = SDL_SCANCODE_K; break;
                case 4: sc = SDL_SCANCODE_G; break;
                case 5: sc = SDL_SCANCODE_H; break;
                case 8: sc = SDL_SCANCODE_W; break;
                case 9: sc = SDL_SCANCODE_S; break;
                case 10: sc = SDL_SCANCODE_A; break;
                case 11: sc = SDL_SCANCODE_D; break;
                default: sc = SDL_SCANCODE_UNKNOWN;
                }
                if(state == 1)
                    memi.sendkeydown(sc);
                else
                    memi.sendkeyup(sc);
                }
                break;
            case SDL_JOYDEVICEADDED:
            case SDL_CONTROLLERDEVICEADDED:
                cout<<"Added joystick "<<event.jdevice.which<<": "<<SDL_JoystickNameForIndex(event.jdevice.which)<<endl;
                if(js) {
                    SDL_JoystickClose(js);
                    js = NULL;
                }
                if(!js) {
                    cout<<"No joystick previously connected, so I'm using that one."<<endl;
                    js = SDL_JoystickOpen(event.jdevice.which);
                }
                break;
            case SDL_JOYDEVICEREMOVED:
            case SDL_CONTROLLERDEVICEREMOVED:
                cout<<"Removed joystick: "<<SDL_JoystickNameForIndex(event.jdevice.which)<<endl;
                if(js) {
                    SDL_JoystickClose(js);
                    js = NULL;
                }
                break;
            case SDL_KEYDOWN:  /* Handle a KEYDOWN event */         
                if(event.key.keysym.scancode==SDL_SCANCODE_Q||
                  (event.key.keysym.scancode==SDL_SCANCODE_C&&(event.key.keysym.mod==KMOD_RCTRL))||
                  (event.key.keysym.scancode==SDL_SCANCODE_C&&(event.key.keysym.mod==KMOD_LCTRL))) {
                    printf("You pressed q or ctrl-c. Exiting.\n");
                    cpui.print_details(filename);
                    printf("%d frames rendered in %f seconds. (%f FPS)\n",ppui.get_frame(),float(clock())/float(CLOCKS_PER_SEC),float(ppui.get_frame())/(float(clock())/float(CLOCKS_PER_SEC)));
                    //SDL_PauseAudio(true);
                    cout<<"Calling SDL_Quit()"<<endl;
                    SDL_Quit();
                    cout<<"Called SDL_Quit()"<<endl;
                    return 0;
                }
                else if(event.key.keysym.scancode==SDL_SCANCODE_R) {
                    cpui.reset(memi.get_rst_addr());
                }
                else if(event.key.keysym.scancode==SDL_SCANCODE_P) {
                    paused=!paused;
                    if(paused) {
                        SDL_PauseAudioDevice(apui.get_id(), true);
                        printf("Paused emulation.\n");
                    }
                    else {
                        SDL_PauseAudioDevice(apui.get_id(), false);
                        printf("Unpaused emulation.\n");
                    }
                }
                else if(event.key.keysym.scancode >= SDL_SCANCODE_1 &&
                        event.key.keysym.scancode <= SDL_SCANCODE_0) {

                    std::cout<<"Saw scancode "<<event.key.keysym.scancode<<endl;
                    printf(" debug output #%d",int(event.key.keysym.scancode- (SDL_SCANCODE_1 - 1)));
                    //util::toggle_log(event.key.keysym.scancode-48);
                    printf("\n");
                }
                else if(event.key.keysym.scancode==SDL_SCANCODE_TAB) {
                    ppui.toggle_table_view();
                }
                else {
                    //printf("Keydown\n");
                    //printf("Time: %d\n",SDL_GetTicks());
                    memi.sendkeydown(event.key.keysym.scancode);
                }
                break;
            case SDL_KEYUP: /* Handle a KEYUP event*/
                //printf("Keyup\n");
                memi.sendkeyup(event.key.keysym.scancode);
                break;
            case SDL_MOUSEMOTION:
                memi.sendmousepos(event.motion.x, event.motion.y);
                break;
            case SDL_MOUSEBUTTONDOWN:
                memi.sendmousedown(event.button.x,event.button.y);
                break;
            case SDL_MOUSEBUTTONUP:
                memi.sendmouseup(event.button.x,event.button.y);
                break;
            //case SDL_VIDEORESIZE:
            case SDL_WINDOWEVENT:
                switch(event.window.event) {
                case SDL_WINDOWEVENT_SIZE_CHANGED:
                    newx=event.window.data1;
                    newy=event.window.data2;
                    if(newx > 0 && newy > 0) {
                        //changed=true;
                    }
                    //ppui.resize(newx,newy);
                    break;
                case SDL_WINDOWEVENT_EXPOSED:
                    //ppui.resize(1,1);
                    break;
                }
                break;
            case SDL_QUIT:
                //SDL_PauseAudio(true);
                SDL_Quit();
                cpui.print_details(filename);
                printf("%d frames rendered in %f seconds. (%f FPS)\n",ppui.get_frame(),float(clock())/float(CLOCKS_PER_SEC),float(ppui.get_frame())/(float(clock())/float(CLOCKS_PER_SEC)));
                return 0;
                break;
            default: /* Report an unhandled event */
                //printf("I don't know what this event is! Flushing it.\n");
                SDL_FlushEvent(event.type);
                break;
            }
        }
        if(!paused) {
            //cout<<"Running the CPU"<<endl;
            int cpu_ret=cpui.run_ops();
            //cout<<"Ran the CPU"<<endl;
            if(cpu_ret < 0) {
                return 1;
            }
            else {
                //cout<<"Frame "<<ppui.get_frame()<<endl;

                int apu_id = apui.get_id();
                if(apu_id > 0) {
                    //cout<<"Locking audio...";
                    SDL_LockAudioDevice(apu_id);
                    //cout<<"done."<<endl;
                    apui.set_frame(ppui.get_frame());
                    apui.gen_audio();
                    //apui.dat.buffered += 735; Dude, do this in gen_audio, not here =/
                    //cout<<"Unlocking audio...";
                    SDL_UnlockAudioDevice(apu_id);
                    //cout<<"done."<<endl;
                }
                //cout<<SDL_GetTicks()<<": Frame: "<<ppui.get_frame()<<" Write pos: "<<apui.write_pos<<endl;
                //cout<<"Running the PPU"<<endl;
                int ppu_ret=ppui.calc();
                //cout<<"Ran the PPU"<<endl;
                if(ppu_ret>0) {
                    if(ppu_ret==1) {
                        //cout<<"Triggering NMI in CPU"<<endl;
                        cpui.trigger_nmi();
                    }
                }
            }
        }

        //Calculates the time that the frame should end at, and delays until that time
        //cout<<"Timing two"<<endl;
        int frames = ppui.get_frame();
        int now = SDL_GetTicks();
        int delay = pstart + int(double(frames) * double(1000) / double(60)) - now;
        //cout<<"Frame: "<<frames<<" now: "<<now<<" delay: "<<delay<<endl;       
        if(delay > 0) {
            SDL_Delay(delay);
        }
    }
    return 0;
}

// Assembly:
subq $0x22448, %rsp          # imm = 0x22448
movl $0x0, 0x22444(%rsp)
movl %edi, 0x22440(%rsp)
movq %rsi, 0x22438(%rsp)
movq 0x2a360(%rip), %rax     # 0x36fc8
movl $0x0, (%rax)
movl $0x1, 0x22430(%rsp)
movl $0x0, 0x2242c(%rsp)
cmpl $0x1, 0x22440(%rsp)
jne 0xccd6
movq 0x2a31b(%rip), %rdi     # 0x36fb0
leaq 0x1e3b0(%rip), %rsi     # 0x2b04c
callq 0x43c0
movq %rax, %rdi
movq 0x22438(%rsp), %rax
movq (%rax), %rsi
callq 0x43c0
movq %rax, %rdi
leaq 0x1e399(%rip), %rsi     # 0x2b057
callq 0x43c0
movq 0x2a2e6(%rip), %rdi     # 0x36fb0
leaq 0x1e41b(%rip), %rsi     # 0x2b0ec
callq 0x43c0
jmp 0xccd8
xorl %eax, %eax
cmpl $0x3, 0x22440(%rsp)
movb %al, 0x1cb(%rsp)
jle 0xcd1d
movl 0x22440(%rsp), %edi
movq 0x22438(%rsp), %rsi
leaq 0x1e422(%rip), %rdx     # 0x2b123
callq 0x40e0
movb %al, 0x22437(%rsp)
movsbl %al, %eax
cmpl $-0x1, %eax
setne %al
movb %al, 0x1cb(%rsp)
movb 0x1cb(%rsp), %al
testb $0x1, %al
jne 0xcd2d
jmp 0xcdef
movsbl 0x22437(%rsp), %eax
movl %eax, 0x1c4(%rsp)
subl $0x64, %eax
je 0xcd5f
jmp 0xcd43
movl 0x1c4(%rsp), %eax
subl $0x6d, %eax
je 0xcd8f
jmp 0xcd51
movl 0x1c4(%rsp), %eax
subl $0x78, %eax
je 0xcd77
jmp 0xcda7
movq 0x2a232(%rip), %rax     # 0x36f98
movq (%rax), %rdi
callq 0x45b0
movl %eax, %edi
callq 0x20c00
jmp 0xcdea
movq 0x2a21a(%rip), %rax     # 0x36f98
movq (%rax), %rdi
callq 0x45b0
movl %eax, 0x22430(%rsp)
jmp 0xcdea
movq 0x2a202(%rip), %rax     # 0x36f98
movq (%rax), %rdi
callq 0x45b0
movl %eax, 0x2242c(%rsp)
jmp 0xcdea
movq 0x2a242(%rip), %rdi     # 0x36ff0
leaq 0x1e375(%rip), %rsi     # 0x2b12a
callq 0x43c0
movq %rax, %rdi
movq 0x2a1e4(%rip), %rax     # 0x36fa8
movl (%rax), %esi
callq 0x4660
movq %rax, %rdi
leaq 0x1e7d0(%rip), %rsi     # 0x2b5a5
callq 0x43c0
movl $0x1, 0x22444(%rsp)
jmp 0xe07b
jmp 0xccd8
cmpl $0x0, 0x22430(%rsp)
jne 0xce04
movl $0x1, 0x22430(%rsp)
leaq 0x22408(%rsp), %rdi
callq 0x4520
movq 0x2a1a8(%rip), %rax     # 0x36fc0
movl (%rax), %eax
cmpl 0x22440(%rsp), %eax
jl 0xce31
cmpl $0x2, 0x22440(%rsp)
jne 0xcf6e
movq 0x22438(%rsp), %rax
movq 0x2a180(%rip), %rcx     # 0x36fc0
movslq (%rcx), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, 0x1b0(%rsp)
leaq 0x223e7(%rsp), %rdi
movq %rdi, 0x1b8(%rsp)
callq 0x4690
movq 0x1b0(%rsp), %rsi
movq 0x1b8(%rsp), %rdx
leaq 0x223e8(%rsp), %rdi
callq 0x4500
jmp 0xce83
leaq 0x22408(%rsp), %rdi
leaq 0x223e8(%rsp), %rsi
movq %rsi, 0x1a0(%rsp)
callq 0x4470
movq 0x1a0(%rsp), %rdi
callq 0x4240
leaq 0x223e7(%rsp), %rdi
callq 0x4410
movq 0x2a0ef(%rip), %rdi     # 0x36fb0
leaq 0x1e272(%rip), %rsi     # 0x2b13a
callq 0x43c0
movq %rax, 0x1a8(%rsp)
jmp 0xced7
movq 0x1a8(%rsp), %rdi
leaq 0x22408(%rsp), %rsi
callq 0x4350
movq %rax, 0x198(%rsp)
jmp 0xcef6
movq 0x198(%rsp), %rdi
leaq 0x1e23e(%rip), %rsi     # 0x2b143
callq 0x43c0
movq %rax, 0x190(%rsp)
jmp 0xcf14
movq 0x190(%rsp), %rdi
movq 0x2a06d(%rip), %rsi     # 0x36f90
callq 0x4400
jmp 0xcf2a
jmp 0xcffc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x223d8(%rsp)
movl %eax, 0x223d4(%rsp)
leaq 0x223e7(%rsp), %rdi
callq 0x4410
jmp 0xe06c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x223d8(%rsp)
movl %eax, 0x223d4(%rsp)
jmp 0xe06c
movq 0x2a03b(%rip), %rdi     # 0x36fb0
leaq 0x1e1cb(%rip), %rsi     # 0x2b147
callq 0x43c0
movq %rax, 0x188(%rsp)
jmp 0xcf8b
movq 0x188(%rsp), %rdi
movq 0x22438(%rsp), %rax
movq (%rax), %rsi
callq 0x43c0
movq %rax, 0x180(%rsp)
jmp 0xcfad
movq 0x180(%rsp), %rdi
leaq 0x1e1b2(%rip), %rsi     # 0x2b16e
callq 0x43c0
movq %rax, 0x178(%rsp)
jmp 0xcfcb
movq 0x178(%rsp), %rdi
movq 0x29fb6(%rip), %rsi     # 0x36f90
callq 0x4400
jmp 0xcfe1
movl $0x1, 0x22444(%rsp)
movl $0x1, 0x223d0(%rsp)
jmp 0xe05d
movb $0x0, 0x223cf(%rsp)
movl $0x10f231, %edi         # imm = 0x10F231
callq 0x4360
movl %eax, 0x174(%rsp)
jmp 0xd017
movl 0x174(%rsp), %eax
cmpl $0x0, %eax
jge 0xd0cc
movl $0x100010, %edi         # imm = 0x100010
callq 0x4360
movl %eax, 0x170(%rsp)
jmp 0xd03a
movl 0x170(%rsp), %eax
cmpl $0x0, %eax
jge 0xd08f
movq 0x29f6b(%rip), %rax     # 0x36fb8
movq (%rax), %rax
movq %rax, 0x160(%rsp)
callq 0x42e0
movq %rax, 0x168(%rsp)
jmp 0xd067
movq 0x168(%rsp), %rdx
movq 0x160(%rsp), %rdi
leaq 0x1e0f9(%rip), %rsi     # 0x2b177
movb $0x0, %al
callq 0x4570
movl $0x1, %edi
callq 0x4450
movb $0x1, 0x223cf(%rsp)
movq 0x29f12(%rip), %rdi     # 0x36fb0
leaq 0x1e0ef(%rip), %rsi     # 0x2b194
callq 0x43c0
movq %rax, 0x158(%rsp)
jmp 0xd0b4
movq 0x158(%rsp), %rdi
movq 0x29ecd(%rip), %rsi     # 0x36f90
callq 0x4400
jmp 0xd0ca
jmp 0xd0cc
movq $0x0, 0x223c0(%rsp)
callq 0x4260
movl %eax, 0x154(%rsp)
jmp 0xd0e6
movl 0x154(%rsp), %eax
movl %eax, 0x223bc(%rsp)
cmpl $0x0, 0x223bc(%rsp)
jle 0xd205
movl $0x0, 0x223b8(%rsp)
movl 0x223b8(%rsp), %eax
cmpl 0x223bc(%rsp), %eax
jge 0xd1b1
movl 0x223b8(%rsp), %edi
callq 0x44e0
movq %rax, 0x148(%rsp)
jmp 0xd137
movq 0x148(%rsp), %rax
movq %rax, 0x223b0(%rsp)
movq 0x29e62(%rip), %rdi     # 0x36fb0
leaq 0x1e08c(%rip), %rsi     # 0x2b1e1
callq 0x43c0
movq %rax, 0x140(%rsp)
jmp 0xd164
movq 0x140(%rsp), %rdi
movq 0x223b0(%rsp), %rsi
callq 0x43c0
movq %rax, 0x138(%rsp)
jmp 0xd183
movq 0x138(%rsp), %rdi
movq 0x29dfe(%rip), %rsi     # 0x36f90
callq 0x4400
jmp 0xd199
jmp 0xd19b
movl 0x223b8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x223b8(%rsp)
jmp 0xd10d
movq 0x29df8(%rip), %rdi     # 0x36fb0
leaq 0x1e033(%rip), %rsi     # 0x2b1f2
callq 0x43c0
movq %rax, 0x130(%rsp)
jmp 0xd1ce
movq 0x130(%rsp), %rdi
movq 0x29db3(%rip), %rsi     # 0x36f90
callq 0x4400
jmp 0xd1e4
xorl %edi, %edi
callq 0x41c0
movq %rax, 0x128(%rsp)
jmp 0xd1f5
movq 0x128(%rsp), %rax
movq %rax, 0x223c0(%rsp)
leaq 0x222c0(%rsp), %rdi
leaq 0x22408(%rsp), %rsi
callq 0x41d0
jmp 0xd21c
movl 0x2242c(%rsp), %edx
leaq 0x222e0(%rsp), %rdi
leaq 0x222c0(%rsp), %rsi
callq 0xebc0
jmp 0xd23a
leaq 0x222c0(%rsp), %rdi
callq 0x4240
movl 0x22430(%rsp), %edx
leaq 0xa58(%rsp), %rdi
leaq 0x222e0(%rsp), %rsi
callq 0x1c590
jmp 0xd265
testb $0x1, 0x222b9(%rsp)
je 0xd308
movb $0x1, 0x223cf(%rsp)
movq 0x29d2e(%rip), %rdi     # 0x36fb0
leaq 0x1df88(%rip), %rsi     # 0x2b211
callq 0x43c0
movq %rax, 0x120(%rsp)
jmp 0xd298
movq 0x120(%rsp), %rdi
movq 0x29ce9(%rip), %rsi     # 0x36f90
callq 0x4400
jmp 0xd2ae
jmp 0xd308
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x223d8(%rsp)
movl %eax, 0x223d4(%rsp)
leaq 0x222c0(%rsp), %rdi
callq 0x4240
jmp 0xe06c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x223d8(%rsp)
movl %eax, 0x223d4(%rsp)
jmp 0xe04e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x223d8(%rsp)
movl %eax, 0x223d4(%rsp)
jmp 0xe041
movzbl 0x223cf(%rsp), %esi
andl $0x1, %esi
leaq 0x810(%rsp), %rdi
callq 0x22d50
jmp 0xd322
leaq 0x810(%rsp), %rdi
callq 0x222f0
movl %eax, 0x11c(%rsp)
jmp 0xd338
movl 0x11c(%rsp), %edi
movl $0x1, %esi
callq 0x44b0
jmp 0xd34b
leaq 0x760(%rsp), %rdi
leaq 0x222e0(%rsp), %rsi
leaq 0xa58(%rsp), %rdx
leaq 0x810(%rsp), %rcx
callq 0x13ca0
jmp 0xd372
leaq 0x810(%rsp), %rdi
leaq 0x760(%rsp), %rsi
callq 0x22fe0
jmp 0xd389
leaq 0x760(%rsp), %rdi
callq 0x14db0
movl %eax, 0x118(%rsp)
jmp 0xd39f
leaq 0x222e0(%rsp), %rdi
callq 0x10f10
movb %al, 0x117(%rsp)
jmp 0xd3b5
movl 0x118(%rsp), %ecx
movb 0x117(%rsp), %al
movzbl %al, %r8d
andl $0x1, %r8d
leaq 0x238(%rsp), %rdi
leaq 0x760(%rsp), %rsi
leaq 0x810(%rsp), %rdx
callq 0x167d0
jmp 0xd3ea
leaq 0x222e0(%rsp), %rdi
callq 0x10f10
movb %al, 0x116(%rsp)
jmp 0xd400
movb 0x116(%rsp), %al
testb $0x1, %al
jne 0xd410
jmp 0xd4e7
movq 0x29b99(%rip), %rdi     # 0x36fb0
leaq 0x1de21(%rip), %rsi     # 0x2b23f
callq 0x43c0
movq %rax, 0x108(%rsp)
jmp 0xd42d
movq 0x108(%rsp), %rdi
movq 0x29b54(%rip), %rsi     # 0x36f90
callq 0x4400
jmp 0xd443
leaq 0x222e0(%rsp), %rdi
leaq 0x810(%rsp), %rsi
leaq 0x760(%rsp), %rdx
leaq 0x238(%rsp), %rcx
callq 0xe0a0
movl %eax, 0x104(%rsp)
jmp 0xd471
movl 0x104(%rsp), %eax
movl %eax, 0x22444(%rsp)
movl $0x1, 0x223d0(%rsp)
jmp 0xdfe4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x223d8(%rsp)
movl %eax, 0x223d4(%rsp)
jmp 0xe034
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x223d8(%rsp)
movl %eax, 0x223d4(%rsp)
jmp 0xe027
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x223d8(%rsp)
movl %eax, 0x223d4(%rsp)
leaq 0x238(%rsp), %rdi
callq 0x173c0
jmp 0xe027
movb $0x0, 0x237(%rsp)
callq 0x43f0
movl %eax, 0x100(%rsp)
jmp 0xd4fd
movl 0x100(%rsp), %eax
movl %eax, 0x230(%rsp)
leaq 0x810(%rsp), %rdi
callq 0x222f0
movl %eax, 0xfc(%rsp)
jmp 0xd521
movl 0xfc(%rsp), %edi
xorl %esi, %esi
callq 0x44b0
jmp 0xd531
jmp 0xd533
jmp 0xd535
jmp 0xd537
leaq 0x1f8(%rsp), %rdi
callq 0x4230
movl %eax, 0xf8(%rsp)
jmp 0xd54d
movl 0xf8(%rsp), %eax
cmpl $0x0, %eax
je 0xde3b
movl 0x1f8(%rsp), %eax
movl %eax, 0xf4(%rsp)
subl $0x100, %eax            # imm = 0x100
je 0xdd5b
jmp 0xd578
movl 0xf4(%rsp), %eax
subl $0x200, %eax            # imm = 0x200
je 0xdd02
jmp 0xd58c
movl 0xf4(%rsp), %eax
subl $0x300, %eax            # imm = 0x300
je 0xd96e
jmp 0xd5a0
movl 0xf4(%rsp), %eax
subl $0x301, %eax            # imm = 0x301
je 0xdc81
jmp 0xd5b4
movl 0xf4(%rsp), %eax
subl $0x400, %eax            # imm = 0x400
je 0xdc9c
jmp 0xd5c8
movl 0xf4(%rsp), %eax
subl $0x401, %eax            # imm = 0x401
je 0xdcbe
jmp 0xd5dc
movl 0xf4(%rsp), %eax
subl $0x402, %eax            # imm = 0x402
je 0xdce0
jmp 0xd5f0
movl 0xf4(%rsp), %eax
addl $0xfffff9fd, %eax       # imm = 0xFFFFF9FD
subl $0x2, %eax
jb 0xd656
jmp 0xd603
movl 0xf4(%rsp), %eax
subl $0x605, %eax            # imm = 0x605
je 0xd7a8
jmp 0xd617
movl 0xf4(%rsp), %eax
subl $0x606, %eax            # imm = 0x606
je 0xd8db
jmp 0xd62b
movl 0xf4(%rsp), %eax
subl $0x653, %eax            # imm = 0x653
je 0xd7a8
jmp 0xd63f
movl 0xf4(%rsp), %eax
subl $0x654, %eax            # imm = 0x654
je 0xd8db
jmp 0xde26
movzbl 0x204(%rsp), %eax
movl %eax, 0x1e8(%rsp)
movzbl 0x205(%rsp), %eax
movl %eax, 0x1e4(%rsp)
movq 0x29935(%rip), %rdi     # 0x36fb0
leaq 0x1dbea(%rip), %rsi     # 0x2b26c
callq 0x43c0
movq %rax, 0xe8(%rsp)
jmp 0xd691
movq 0xe8(%rsp), %rdi
movl 0x1e8(%rsp), %esi
callq 0x4660
movq %rax, 0xe0(%rsp)
jmp 0xd6af
movq 0xe0(%rsp), %rdi
movq 0x298d2(%rip), %rsi     # 0x36f90
callq 0x4400
jmp 0xd6c5
movl 0x1e8(%rsp), %eax
movq %rax, 0xd8(%rsp)
subq $0xb, %rax
ja 0xd75e
movq 0xd8(%rsp), %rax
leaq 0x1d92f(%rip), %rcx     # 0x2b01c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl $0xf, 0x1ec(%rsp)
jmp 0xd769
movl $0xe, 0x1ec(%rsp)
jmp 0xd769
movl $0xa, 0x1ec(%rsp)
jmp 0xd769
movl $0xb, 0x1ec(%rsp)
jmp 0xd769
movl $0x1a, 0x1ec(%rsp)
jmp 0xd769
movl $0x16, 0x1ec(%rsp)
jmp 0xd769
movl $0x4, 0x1ec(%rsp)
jmp 0xd769
movl $0x7, 0x1ec(%rsp)
jmp 0xd769
movl $0x0, 0x1ec(%rsp)
cmpl $0x1, 0x1e4(%rsp)
jne 0xd78b
movl 0x1ec(%rsp), %esi
leaq 0x760(%rsp), %rdi
callq 0x13f30
jmp 0xd789
jmp 0xd7a3
movl 0x1ec(%rsp), %esi
leaq 0x760(%rsp), %rdi
callq 0x141c0
jmp 0xd7a1
jmp 0xd7a3
jmp 0xde36
movq 0x29801(%rip), %rdi     # 0x36fb0
leaq 0x1dac3(%rip), %rsi     # 0x2b279
callq 0x43c0
movq %rax, 0xd0(%rsp)
jmp 0xd7c5
movq 0xd0(%rsp), %rdi
movl 0x200(%rsp), %esi
callq 0x4660
movq %rax, 0xc8(%rsp)
jmp 0xd7e3
movq 0xc8(%rsp), %rdi
leaq 0x1f423(%rip), %rsi     # 0x2cc15
callq 0x43c0
movq %rax, 0xc0(%rsp)
jmp 0xd801
movl 0x200(%rsp), %edi
callq 0x44e0
movq %rax, 0xb8(%rsp)
jmp 0xd817
movq 0xb8(%rsp), %rsi
movq 0xc0(%rsp), %rdi
callq 0x43c0
movq %rax, 0xb0(%rsp)
jmp 0xd836
movq 0xb0(%rsp), %rdi
movq 0x2974b(%rip), %rsi     # 0x36f90
callq 0x4400
jmp 0xd84c
cmpq $0x0, 0x223c0(%rsp)
je 0xd872
movq 0x223c0(%rsp), %rdi
callq 0x41b0
jmp 0xd866
movq $0x0, 0x223c0(%rsp)
cmpq $0x0, 0x223c0(%rsp)
jne 0xd8d6
movq 0x2972c(%rip), %rdi     # 0x36fb0
leaq 0x1d9fe(%rip), %rsi     # 0x2b289
callq 0x43c0
movq %rax, 0xa8(%rsp)
jmp 0xd89a
movq 0xa8(%rsp), %rdi
movq 0x296e7(%rip), %rsi     # 0x36f90
callq 0x4400
jmp 0xd8b0
movl 0x200(%rsp), %edi
callq 0x41c0
movq %rax, 0xa0(%rsp)
jmp 0xd8c6
movq 0xa0(%rsp), %rax
movq %rax, 0x223c0(%rsp)
jmp 0xde36
movq 0x296ce(%rip), %rdi     # 0x36fb0
leaq 0x1d9d9(%rip), %rsi     # 0x2b2c2
callq 0x43c0
movq %rax, 0x98(%rsp)
jmp 0xd8f8
movl 0x200(%rsp), %edi
callq 0x44e0
movq %rax, 0x90(%rsp)
jmp 0xd90e
movq 0x90(%rsp), %rsi
movq 0x98(%rsp), %rdi
callq 0x43c0
movq %rax, 0x88(%rsp)
jmp 0xd92d
movq 0x88(%rsp), %rdi
movq 0x29654(%rip), %rsi     # 0x36f90
callq 0x4400
jmp 0xd943
cmpq $0x0, 0x223c0(%rsp)
je 0xd969
movq 0x223c0(%rsp), %rdi
callq 0x41b0
jmp 0xd95d
movq $0x0, 0x223c0(%rsp)
jmp 0xde36
cmpl $0x14, 0x208(%rsp)
je 0xd9b0
cmpl $0x6, 0x208(%rsp)
jne 0xd991
movzwl 0x210(%rsp), %eax
cmpl $0x80, %eax
je 0xd9b0
cmpl $0x6, 0x208(%rsp)
jne 0xdaf1
movzwl 0x210(%rsp), %eax
cmpl $0x40, %eax
jne 0xdaf1
leaq 0x1d91e(%rip), %rdi     # 0x2b2d5
xorl %eax, %eax
callq 0x4050
jmp 0xd9c0
leaq 0x238(%rsp), %rdi
leaq 0x22408(%rsp), %rsi
callq 0x169e0
jmp 0xd9d7
leaq 0xa58(%rsp), %rdi
callq 0x1fca0
movl %eax, 0x84(%rsp)
jmp 0xd9ed
callq 0x4280
cvtsi2ss %rax, %xmm0
movss 0x1d619(%rip), %xmm1    # 0x2b018
divss %xmm1, %xmm0
cvtss2sd %xmm0, %xmm0
movsd %xmm0, 0x78(%rsp)
leaq 0xa58(%rsp), %rdi
callq 0x1fca0
movl %eax, 0x80(%rsp)
jmp 0xda23
movl 0x80(%rsp), %eax
cvtsi2ss %eax, %xmm0
movss %xmm0, 0x74(%rsp)
callq 0x4280
movss 0x74(%rsp), %xmm1
movl 0x84(%rsp), %esi
movsd 0x78(%rsp), %xmm0
cvtsi2ss %rax, %xmm2
movss 0x1d5bf(%rip), %xmm3    # 0x2b018
divss %xmm3, %xmm2
divss %xmm2, %xmm1
cvtss2sd %xmm1, %xmm1
leaq 0x1d88c(%rip), %rdi     # 0x2b2f8
movb $0x2, %al
callq 0x4050
jmp 0xda75
movq 0x29534(%rip), %rdi     # 0x36fb0
leaq 0x1d8a1(%rip), %rsi     # 0x2b324
callq 0x43c0
movq %rax, 0x68(%rsp)
jmp 0xda8f
movq 0x68(%rsp), %rdi
movq 0x294f5(%rip), %rsi     # 0x36f90
callq 0x4400
jmp 0xdaa2
callq 0x40a0
jmp 0xdaa9
movq 0x29500(%rip), %rdi     # 0x36fb0
leaq 0x1d880(%rip), %rsi     # 0x2b337
callq 0x43c0
movq %rax, 0x60(%rsp)
jmp 0xdac3
movq 0x60(%rsp), %rdi
movq 0x294c1(%rip), %rsi     # 0x36f90
callq 0x4400
jmp 0xdad6
movl $0x0, 0x22444(%rsp)
movl $0x1, 0x223d0(%rsp)
jmp 0xdfe4
cmpl $0x15, 0x208(%rsp)
jne 0xdb26
leaq 0x760(%rsp), %rdi
callq 0x14db0
movl %eax, 0x5c(%rsp)
jmp 0xdb0e
movl 0x5c(%rsp), %esi
leaq 0x238(%rsp), %rdi
callq 0x195d0
jmp 0xdb21
jmp 0xdc7a
cmpl $0x13, 0x208(%rsp)
jne 0xdbbc
movb 0x237(%rsp), %al
xorb $-0x1, %al
andb $0x1, %al
movb %al, 0x237(%rsp)
testb $0x1, 0x237(%rsp)
je 0xdb85
leaq 0x810(%rsp), %rdi
callq 0x222f0
movl %eax, 0x58(%rsp)
jmp 0xdb63
movl 0x58(%rsp), %edi
movl $0x1, %esi
callq 0x44b0
jmp 0xdb73
leaq 0x1d7cf(%rip), %rdi     # 0x2b349
xorl %eax, %eax
callq 0x4050
jmp 0xdb83
jmp 0xdbb7
leaq 0x810(%rsp), %rdi
callq 0x222f0
movl %eax, 0x54(%rsp)
jmp 0xdb98
movl 0x54(%rsp), %edi
xorl %esi, %esi
callq 0x44b0
jmp 0xdba5
leaq 0x1d7b0(%rip), %rdi     # 0x2b35c
xorl %eax, %eax
callq 0x4050
jmp 0xdbb5
jmp 0xdbb7
jmp 0xdc78
cmpl $0x1e, 0x208(%rsp)
jl 0xdc41
cmpl $0x27, 0x208(%rsp)
jg 0xdc41
movq 0x293d9(%rip), %rdi     # 0x36fb0
leaq 0x1d793(%rip), %rsi     # 0x2b371
callq 0x43c0
movq %rax, 0x48(%rsp)
jmp 0xdbea
movq 0x48(%rsp), %rdi
movl 0x208(%rsp), %esi
callq 0x4660
movq %rax, 0x40(%rsp)
jmp 0xdc02
movq 0x40(%rsp), %rdi
movq 0x29382(%rip), %rsi     # 0x36f90
callq 0x4400
jmp 0xdc15
movl 0x208(%rsp), %esi
addl $-0x1d, %esi
leaq 0x1d759(%rip), %rdi     # 0x2b37f
xorl %eax, %eax
callq 0x4050
jmp 0xdc2f
leaq 0x1dec1(%rip), %rdi     # 0x2baf7
xorl %eax, %eax
callq 0x4050
jmp 0xdc3f
jmp 0xdc76
cmpl $0x2b, 0x208(%rsp)
jne 0xdc5c
leaq 0xa58(%rsp), %rdi
callq 0x1fcf0
jmp 0xdc5a
jmp 0xdc74
movl 0x208(%rsp), %esi
leaq 0x760(%rsp), %rdi
callq 0x13f30
jmp 0xdc72
jmp 0xdc74
jmp 0xdc76
jmp 0xdc78
jmp 0xdc7a
jmp 0xdc7c
jmp 0xde36
movl 0x208(%rsp), %esi
leaq 0x760(%rsp), %rdi
callq 0x141c0
jmp 0xdc97
jmp 0xde36
movl 0x20c(%rsp), %esi
movl 0x210(%rsp), %edx
leaq 0x760(%rsp), %rdi
callq 0x143f0
jmp 0xdcb9
jmp 0xde36
movl 0x20c(%rsp), %esi
movl 0x210(%rsp), %edx
leaq 0x760(%rsp), %rdi
callq 0x14440
jmp 0xdcdb
jmp 0xde36
movl 0x20c(%rsp), %esi
movl 0x210(%rsp), %edx
leaq 0x760(%rsp), %rdi
callq 0x14420
jmp 0xdcfd
jmp 0xde36
movzbl 0x204(%rsp), %eax
movl %eax, 0x3c(%rsp)
subl $0x3, %eax
je 0xdd54
jmp 0xdd15
movl 0x3c(%rsp), %eax
subl $0x6, %eax
jne 0xdd56
jmp 0xdd20
movl 0x208(%rsp), %eax
movl %eax, 0x1f4(%rsp)
movl 0x20c(%rsp), %eax
movl %eax, 0x1f0(%rsp)
cmpl $0x0, 0x1f4(%rsp)
jle 0xdd52
cmpl $0x0, 0x1f0(%rsp)
jle 0xdd52
jmp 0xdd52
jmp 0xdd56
jmp 0xdd56
jmp 0xde36
callq 0x40a0
jmp 0xdd62
leaq 0x238(%rsp), %rdi
leaq 0x22408(%rsp), %rsi
callq 0x169e0
jmp 0xdd79
leaq 0xa58(%rsp), %rdi
callq 0x1fca0
movl %eax, 0x38(%rsp)
jmp 0xdd8c
callq 0x4280
cvtsi2ss %rax, %xmm0
movss 0x1d27a(%rip), %xmm1    # 0x2b018
divss %xmm1, %xmm0
cvtss2sd %xmm0, %xmm0
movsd %xmm0, 0x28(%rsp)
leaq 0xa58(%rsp), %rdi
callq 0x1fca0
movl %eax, 0x34(%rsp)
jmp 0xddbf
movl 0x34(%rsp), %eax
cvtsi2ss %eax, %xmm0
movss %xmm0, 0x24(%rsp)
callq 0x4280
movss 0x24(%rsp), %xmm1
movl 0x38(%rsp), %esi
movsd 0x28(%rsp), %xmm0
cvtsi2ss %rax, %xmm2
movss 0x1d229(%rip), %xmm3    # 0x2b018
divss %xmm3, %xmm2
divss %xmm2, %xmm1
cvtss2sd %xmm1, %xmm1
leaq 0x1d4f6(%rip), %rdi     # 0x2b2f8
movb $0x2, %al
callq 0x4050
jmp 0xde0b
movl $0x0, 0x22444(%rsp)
movl $0x1, 0x223d0(%rsp)
jmp 0xdfe4
movl 0x1f8(%rsp), %edi
callq 0x46f0
jmp 0xde34
jmp 0xde36
jmp 0xd537
testb $0x1, 0x237(%rsp)
jne 0xdf55
leaq 0x238(%rsp), %rdi
callq 0x190d0
movl %eax, 0x20(%rsp)
jmp 0xde5c
movl 0x20(%rsp), %eax
movl %eax, 0x1e0(%rsp)
cmpl $0x0, 0x1e0(%rsp)
jge 0xde8c
movl $0x1, 0x22444(%rsp)
movl $0x1, 0x223d0(%rsp)
jmp 0xdfe4
leaq 0x810(%rsp), %rdi
callq 0x222f0
movl %eax, 0x1c(%rsp)
jmp 0xde9f
movl 0x1c(%rsp), %eax
movl %eax, 0x1dc(%rsp)
cmpl $0x0, 0x1dc(%rsp)
jle 0xdf0c
movl 0x1dc(%rsp), %edi
callq 0x43a0
jmp 0xdec2
leaq 0xa58(%rsp), %rdi
callq 0x1fca0
movl %eax, 0x18(%rsp)
jmp 0xded5
movl 0x18(%rsp), %esi
leaq 0x810(%rsp), %rdi
callq 0x22300
jmp 0xdee8
leaq 0x810(%rsp), %rdi
movl $0x2df, %esi            # imm = 0x2DF
callq 0x23650
jmp 0xdefc
movl 0x1dc(%rsp), %edi
callq 0x4650
jmp 0xdf0a
jmp 0xdf0c
leaq 0xa58(%rsp), %rdi
callq 0x1e990
movl %eax, 0x14(%rsp)
jmp 0xdf1f
movl 0x14(%rsp), %eax
movl %eax, 0x1d8(%rsp)
cmpl $0x0, 0x1d8(%rsp)
jle 0xdf51
cmpl $0x1, 0x1d8(%rsp)
jne 0xdf4f
leaq 0x238(%rsp), %rdi
callq 0x19510
jmp 0xdf4d
jmp 0xdf4f
jmp 0xdf51
jmp 0xdf53
jmp 0xdf55
leaq 0xa58(%rsp), %rdi
callq 0x1fca0
movl %eax, 0x10(%rsp)
jmp 0xdf68
movl 0x10(%rsp), %eax
movl %eax, 0x1d4(%rsp)
callq 0x43f0
movl %eax, 0xc(%rsp)
jmp 0xdf7e
movl 0xc(%rsp), %eax
movl %eax, 0x1d0(%rsp)
movl 0x230(%rsp), %eax
cvtsi2sdl 0x1d4(%rsp), %xmm0
movsd 0x1d06f(%rip), %xmm1    # 0x2b010
mulsd %xmm1, %xmm0
movsd 0x1d05b(%rip), %xmm1    # 0x2b008
divsd %xmm1, %xmm0
cvttsd2si %xmm0, %ecx
addl %ecx, %eax
subl 0x1d0(%rsp), %eax
movl %eax, 0x1cc(%rsp)
cmpl $0x0, 0x1cc(%rsp)
jle 0xdfdf
movl 0x1cc(%rsp), %edi
callq 0x42d0
jmp 0xdfdd
jmp 0xdfdf
jmp 0xd533
leaq 0x238(%rsp), %rdi
callq 0x173c0
leaq 0x760(%rsp), %rdi
callq 0x13ed0
leaq 0x810(%rsp), %rdi
callq 0x248b0
leaq 0xa58(%rsp), %rdi
callq 0x1cd60
leaq 0x222e0(%rsp), %rdi
callq 0x11050
jmp 0xe05d
leaq 0x760(%rsp), %rdi
callq 0x13ed0
leaq 0x810(%rsp), %rdi
callq 0x248b0
leaq 0xa58(%rsp), %rdi
callq 0x1cd60
leaq 0x222e0(%rsp), %rdi
callq 0x11050
jmp 0xe06c
leaq 0x22408(%rsp), %rdi
callq 0x4240
jmp 0xe07b
leaq 0x22408(%rsp), %rdi
callq 0x4240
jmp 0xe08a
movl 0x22444(%rsp), %eax
addq $0x22448, %rsp          # imm = 0x22448
retq
movq 0x223d8(%rsp), %rdi
callq 0x4680
nopw (%rax,%rax)