// File: nicoeps[P]NicoGB/src/main.cpp
// Function: run(NicoGB&)
void run(NicoGB& nicogb) {
    const int SCALE = 4;
    const int WIDTH = 160;
    const int HEIGHT = 144;

    SDL_Init(SDL_INIT_VIDEO);
    SDL_Window *window = SDL_CreateWindow("NicoGB",
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
        WIDTH*SCALE, HEIGHT*SCALE, 0);
    SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
    SDL_Texture *texture = SDL_CreateTexture(renderer,
    SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, 160, 144);
    SDL_UpdateTexture(texture, NULL, nicogb.framebuffer.data(), 160 * sizeof(uint32_t));

    SDL_Event event;
    SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
    std::string path;
    Key key;

    auto last = millis();
    bool run = true;
    while (run) {
        nicogb.tick();

        if (millis() - last >= 1000/60) {
            last = millis();

            SDL_UpdateTexture(texture, NULL, nicogb.framebuffer.data(), 160 * sizeof(uint32_t));
            SDL_RenderClear(renderer);
            SDL_RenderCopy(renderer, texture, NULL, NULL);
            SDL_RenderPresent(renderer);

            while (SDL_PollEvent(&event)) {
                switch (event.type) {
                    case SDL_QUIT:
                        run = false;
                        break;

                    case SDL_DROPFILE:
                        path = event.drop.file;
                        nicogb.load(path);
                        SDL_SetWindowTitle(window, (std::string("NicoGB - ") + nicogb.title).c_str());
                        break;

                    case SDL_KEYDOWN:
                        switch (event.key.keysym.sym) {
                            case SDLK_q:
                                run = false;
                                break;
                            case SDLK_r:
                                nicogb.init();
                                break;
                            case SDLK_SPACE:
                                nicogb.speed = !nicogb.speed;
                                break;
                            default:
                                key = getKey(event.key.keysym.sym);
                                nicogb.keyDown(key);
                                break;
                        }
                        break;

                    case SDL_KEYUP:
                        key = getKey(event.key.keysym.sym);
                        nicogb.keyUp(key);
                        break;

                    default: break;
                }
            }
        }
    }
    SDL_DestroyTexture(texture);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
}

// Assembly:
subq $0x168, %rsp            # imm = 0x168
movq %rdi, 0x160(%rsp)
movl $0x4, 0x15c(%rsp)
movl $0xa0, 0x158(%rsp)
movl $0x90, 0x154(%rsp)
movl $0x20, %edi
callq 0x3250
leaq 0xa033(%rip), %rdi      # 0x16924
movl $0x1fff0000, %edx       # imm = 0x1FFF0000
movl $0x280, %ecx            # imm = 0x280
movl %ecx, 0x48(%rsp)
movl $0x240, %r8d            # imm = 0x240
xorl %r9d, %r9d
movl %r9d, 0x4c(%rsp)
movl %edx, %esi
callq 0x3050
movl 0x4c(%rsp), %edx
movq %rax, 0x148(%rsp)
movq 0x148(%rsp), %rdi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x3040
movq %rax, 0x140(%rsp)
movq 0x140(%rsp), %rdi
movl $0x16362004, %esi       # imm = 0x16362004
movl $0x2, %edx
movl $0xa0, %ecx
movl $0x90, %r8d
callq 0x3400
movq %rax, 0x138(%rsp)
movq 0x138(%rsp), %rax
movq %rax, 0x40(%rsp)
movq 0x160(%rsp), %rax
movq 0x2c0(%rax), %rdi
callq 0xcf60
movq 0x40(%rsp), %rdi
movl 0x48(%rsp), %ecx
movq %rax, %rdx
movl 0x4c(%rsp), %eax
movl %eax, %esi
callq 0x31f0
movl $0x1000, %edi           # imm = 0x1000
movl $0x1, %esi
callq 0x3140
leaq 0xe0(%rsp), %rdi
callq 0x3330
callq 0xc790
movq %rax, 0x50(%rsp)
jmp 0xc9c4
movq 0x50(%rsp), %rax
movq %rax, 0xd0(%rsp)
movb $0x1, 0xc3(%rsp)
testb $0x1, 0xc3(%rsp)
je 0xcd83
movq 0x160(%rsp), %rdi
callq 0x10110
jmp 0xc9f6
callq 0xc790
movq %rax, 0x38(%rsp)
jmp 0xca02
movq 0x38(%rsp), %rax
subq 0xd0(%rsp), %rax
cmpq $0x10, %rax
jl 0xcd7e
callq 0xc790
movq %rax, 0x30(%rsp)
jmp 0xca25
movq 0x30(%rsp), %rax
movq %rax, 0xd0(%rsp)
movq 0x138(%rsp), %rax
movq %rax, 0x28(%rsp)
movq 0x160(%rsp), %rax
movq 0x2c0(%rax), %rdi
callq 0xcf60
movq 0x28(%rsp), %rdi
movq %rax, %rdx
xorl %eax, %eax
movl %eax, %esi
movl $0x280, %ecx            # imm = 0x280
callq 0x31f0
jmp 0xca6b
movq 0x140(%rsp), %rdi
callq 0x3260
jmp 0xca7a
movq 0x140(%rsp), %rdi
movq 0x138(%rsp), %rsi
xorl %eax, %eax
movl %eax, %ecx
movq %rcx, %rdx
callq 0x32d0
jmp 0xca98
movq 0x140(%rsp), %rdi
callq 0x3080
jmp 0xcaa7
jmp 0xcaa9
leaq 0x100(%rsp), %rdi
callq 0x3190
movl %eax, 0x24(%rsp)
jmp 0xcabc
movl 0x24(%rsp), %eax
cmpl $0x0, %eax
je 0xcd7c
movl 0x100(%rsp), %eax
movl %eax, 0x20(%rsp)
subl $0x100, %eax            # imm = 0x100
je 0xcb28
jmp 0xcadd
movl 0x20(%rsp), %eax
subl $0x300, %eax            # imm = 0x300
je 0xccb6
jmp 0xcaee
movl 0x20(%rsp), %eax
subl $0x301, %eax            # imm = 0x301
je 0xcd4a
jmp 0xcaff
movl 0x20(%rsp), %eax
subl $0x1000, %eax           # imm = 0x1000
je 0xcb35
jmp 0xcd75
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc8(%rsp)
movl %eax, 0xc4(%rsp)
jmp 0xcdcc
movb $0x0, 0xc3(%rsp)
jmp 0xcd77
movq 0x108(%rsp), %rsi
leaq 0xe0(%rsp), %rdi
callq 0x3320
jmp 0xcb4c
movq 0x160(%rsp), %rax
movq %rax, 0x18(%rsp)
leaq 0xa0(%rsp), %rdi
leaq 0xe0(%rsp), %rsi
callq 0x3120
jmp 0xcb70
movq 0x18(%rsp), %rdi
leaq 0xa0(%rsp), %rsi
callq 0x10080
jmp 0xcb84
leaq 0xa0(%rsp), %rdi
callq 0x31a0
movq 0x148(%rsp), %rax
movq %rax, 0x8(%rsp)
leaq 0x5f(%rsp), %rdi
movq %rdi, 0x10(%rsp)
callq 0x33e0
movq 0x10(%rsp), %rdx
leaq 0x9d72(%rip), %rsi      # 0x1692b
leaq 0x60(%rsp), %rdi
callq 0xcfd0
jmp 0xcbc5
movq 0x160(%rsp), %rax
movq 0x2b8(%rax), %rdx
leaq 0x80(%rsp), %rdi
leaq 0x60(%rsp), %rsi
callq 0xcf80
jmp 0xcbe8
leaq 0x80(%rsp), %rdi
callq 0x3110
movq 0x8(%rsp), %rdi
movq %rax, %rsi
callq 0x33c0
jmp 0xcc04
leaq 0x80(%rsp), %rdi
callq 0x31a0
leaq 0x60(%rsp), %rdi
callq 0x31a0
leaq 0x5f(%rsp), %rdi
callq 0x32a0
jmp 0xcd77
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc8(%rsp)
movl %eax, 0xc4(%rsp)
leaq 0xa0(%rsp), %rdi
callq 0x31a0
jmp 0xcdcc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc8(%rsp)
movl %eax, 0xc4(%rsp)
jmp 0xcca7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc8(%rsp)
movl %eax, 0xc4(%rsp)
jmp 0xcc9d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc8(%rsp)
movl %eax, 0xc4(%rsp)
leaq 0x80(%rsp), %rdi
callq 0x31a0
leaq 0x60(%rsp), %rdi
callq 0x31a0
leaq 0x5f(%rsp), %rdi
callq 0x32a0
jmp 0xcdcc
movl 0x114(%rsp), %eax
movl %eax, 0x4(%rsp)
subl $0x20, %eax
je 0xccf9
jmp 0xccc8
movl 0x4(%rsp), %eax
subl $0x71, %eax
je 0xccde
jmp 0xccd3
movl 0x4(%rsp), %eax
subl $0x72, %eax
je 0xcce8
jmp 0xcd1d
movb $0x0, 0xc3(%rsp)
jmp 0xcd48
movq 0x160(%rsp), %rdi
callq 0xfff0
jmp 0xccf7
jmp 0xcd48
movq 0x160(%rsp), %rax
movb 0x2a8(%rax), %cl
xorb $-0x1, %cl
movq 0x160(%rsp), %rax
andb $0x1, %cl
movb %cl, 0x2a8(%rax)
jmp 0xcd48
movl 0x114(%rsp), %edi
callq 0xc7d0
movl %eax, 0xdc(%rsp)
movq 0x160(%rsp), %rdi
movl 0xdc(%rsp), %esi
callq 0x101e0
jmp 0xcd46
jmp 0xcd48
jmp 0xcd77
movl 0x114(%rsp), %edi
callq 0xc7d0
movl %eax, 0xdc(%rsp)
movq 0x160(%rsp), %rdi
movl 0xdc(%rsp), %esi
callq 0x10210
jmp 0xcd73
jmp 0xcd77
jmp 0xcd77
jmp 0xcaa9
jmp 0xcd7e
jmp 0xc9d9
movq 0x138(%rsp), %rdi
callq 0x31e0
jmp 0xcd92
movq 0x140(%rsp), %rdi
callq 0x3100
jmp 0xcda1
movq 0x148(%rsp), %rdi
callq 0x3030
jmp 0xcdb0
callq 0x3070
jmp 0xcdb7
leaq 0xe0(%rsp), %rdi
callq 0x31a0
addq $0x168, %rsp            # imm = 0x168
retq
leaq 0xe0(%rsp), %rdi
callq 0x31a0
movq 0xc8(%rsp), %rdi
callq 0x33d0
nopw %cs:(%rax,%rax)