// File: /workspace/github_c_makefile_star2_O3/theandrew168[P]skylark/src/main.c
// Function: main
int
main(int argc, char* argv[])
{
    if (argc != 2) {
        fprintf(stderr, "usage: %s <rom_file>\n", argv[0]);
        return EXIT_FAILURE;
    }

    FILE* fp = fopen(argv[1], "rb");
    if (fp == NULL) {
        fprintf(stderr, "failed to open rom: %s\n", argv[1]);
        return EXIT_FAILURE;
    }

    fseek(fp, 0, SEEK_END);
    long size = ftell(fp);
    fseek(fp, 0, SEEK_SET);

    uint8_t* buf = malloc(size);
    if (buf == NULL) {
        fclose(fp);
        fprintf(stderr, "failed to allocate buffer to hold ROM contents\n");
        return EXIT_FAILURE;
    }

    long count = fread(buf, 1, size, fp);
    if (count != size) {
        free(buf);
        fclose(fp);
        fprintf(stderr, "failed to read ROM into buffer\n");
        return EXIT_FAILURE;
    }
    fclose(fp);

    struct chip8 chip8 = { 0 };
    chip8_init(&chip8);

    int rc = chip8_load(&chip8, buf, size);
    if (rc != CHIP8_OK) {
        free(buf);
        fprintf(stderr, "failed to init chip8 emulator\n");
        return EXIT_FAILURE;
    }
    free(buf);

    if (SDL_Init(SDL_INIT_VIDEO) != 0) {
        fprintf(stderr, "failed to init SDL2: %s\n", SDL_GetError());
        return EXIT_FAILURE;
    }

    SDL_Window* window = SDL_CreateWindow(
        "Skylark CHIP-8 Emulator",
        SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        CHIP8_DISPLAY_WIDTH * SKYLARK_DISPLAY_PIXEL_SIZE,
        CHIP8_DISPLAY_HEIGHT * SKYLARK_DISPLAY_PIXEL_SIZE,
        SDL_WINDOW_RESIZABLE);
    if (window == NULL) {
        fprintf(stderr, "failed to create SDL2 window: %s\n", SDL_GetError());
        return EXIT_FAILURE;
    }

    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    if (renderer == NULL) {
        fprintf(stderr, "failed to create SDL2 renderer: %s\n", SDL_GetError());
        SDL_DestroyWindow(window);
        return EXIT_FAILURE;
    }

    bool running = true;
    while (running) {
        // input
        SDL_Event event = { 0 };
        while (SDL_PollEvent(&event)) {
            if (event.type == SDL_QUIT) running = false;
            if (event.type == SDL_KEYUP) {
                SDL_Keycode key = event.key.keysym.sym;
                if (key == SDLK_ESCAPE) running = false;
            }
        }

        // execute the next instruction
        rc = chip8_step(&chip8);
        if (rc != CHIP8_OK) {
            running = false;
            break;
        }

        // graphics
        SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
        SDL_RenderClear(renderer);

        SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
        for (long y = 0; y < CHIP8_DISPLAY_HEIGHT; y++) {
            for (long x = 0; x < CHIP8_DISPLAY_WIDTH; x++) {
                if (!chip8_pixel_on(&chip8, x, y)) continue;

                SDL_Rect pixel = {
                    .w = SKYLARK_DISPLAY_PIXEL_SIZE,
                    .h = SKYLARK_DISPLAY_PIXEL_SIZE,
                    .x = x * SKYLARK_DISPLAY_PIXEL_SIZE,
                    .y = y * SKYLARK_DISPLAY_PIXEL_SIZE,
                };
                SDL_RenderFillRect(renderer, &pixel);
            }
        }
        SDL_RenderPresent(renderer);
    }

    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();

    return EXIT_SUCCESS;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18a8, %rsp           # imm = 0x18A8
movq %rsi, %r14
cmpl $0x2, %edi
jne 0x26ee
movq 0x8(%r14), %rdi
leaq 0x1b86(%rip), %rsi      # 0x401a
callq 0x2170
testq %rax, %rax
je 0x26f8
movq %rax, %rbx
movq %rax, %rdi
xorl %esi, %esi
movl $0x2, %edx
callq 0x2160
movq %rbx, %rdi
callq 0x2030
movq %rax, %r14
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2160
movq %r14, %rdi
callq 0x2190
testq %rax, %rax
je 0x2706
movq %rax, %r15
movl $0x1, %esi
movq %rax, %rdi
movq %r14, %rdx
movq %rbx, %rcx
callq 0x21c0
cmpq %r14, %rax
jne 0x2710
movq %rbx, %rdi
callq 0x2150
leaq 0x60(%rsp), %rbx
movl $0x1848, %edx           # imm = 0x1848
movq %rbx, %rdi
xorl %esi, %esi
callq 0x20c0
movq %rbx, %rdi
callq 0x2754
movq %rbx, %rdi
movq %r15, %rsi
movq %r14, %rdx
callq 0x27ae
movl %eax, %ebx
movq %r15, %rdi
callq 0x2180
testl %ebx, %ebx
jne 0x271d
movl $0x20, %edi
callq 0x2110
testl %eax, %eax
jne 0x2724
leaq 0x1b65(%rip), %rdi      # 0x40bd
movl $0x1fff0000, %esi       # imm = 0x1FFF0000
movl $0x1fff0000, %edx       # imm = 0x1FFF0000
movl $0x400, %ecx            # imm = 0x400
movl $0x200, %r8d            # imm = 0x200
movl $0x20, %r9d
callq 0x2060
testq %rax, %rax
je 0x272b
movq %rax, %rbx
movq %rax, %rdi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl $0x2, %edx
callq 0x2050
testq %rax, %rax
je 0x2732
movq %rax, %r14
movq %rbx, 0x8(%rsp)
leaq 0x20(%rsp), %rbx
leaq 0x60(%rsp), %r12
xorps %xmm0, %xmm0
movaps %xmm0, 0x40(%rsp)
movaps %xmm0, 0x30(%rsp)
movaps %xmm0, 0x20(%rsp)
movq $0x0, 0x50(%rsp)
movq %rbx, %rdi
callq 0x20d0
testl %eax, %eax
je 0x260e
movb $0x1, %cl
movl 0x20(%rsp), %eax
movl 0x34(%rsp), %edx
cmpl $0x100, %eax            # imm = 0x100
setne %bpl
xorl $0x301, %eax            # imm = 0x301
xorl $0x1b, %edx
orl %eax, %edx
setne %al
andb %cl, %bpl
andb %al, %bpl
movq %rbx, %rdi
callq 0x20d0
movl %ebp, %ecx
testl %eax, %eax
jne 0x25da
jmp 0x2611
movb $0x1, %bpl
movq %r12, %rdi
callq 0x27fd
testl %eax, %eax
jne 0x26d3
movb %bpl, 0x7(%rsp)
movq %r14, %rdi
xorl %esi, %esi
xorl %edx, %edx
xorl %ecx, %ecx
movl $0xff, %r8d
callq 0x21a0
movq %r14, %rdi
callq 0x2130
movq %r14, %rdi
movl $0xff, %esi
movl $0xff, %edx
movl $0xff, %ecx
movl $0xff, %r8d
callq 0x21a0
xorl %ebp, %ebp
movl %ebp, %r13d
shll $0x4, %r13d
xorl %r15d, %r15d
xorl %ebx, %ebx
movq %r12, %rdi
movq %rbx, %rsi
movq %rbp, %rdx
callq 0x2886
testb %al, %al
je 0x26a5
movl %r15d, 0x10(%rsp)
movl %r13d, 0x14(%rsp)
movabsq $0x1000000010, %rax     # imm = 0x1000000010
movq %rax, 0x18(%rsp)
movq %r14, %rdi
leaq 0x10(%rsp), %rsi
callq 0x20b0
incq %rbx
addl $0x10, %r15d
cmpq $0x40, %rbx
jne 0x266d
incq %rbp
cmpq $0x20, %rbp
jne 0x2661
movq %r14, %rdi
callq 0x2080
cmpb $0x0, 0x7(%rsp)
leaq 0x20(%rsp), %rbx
jne 0x25b1
movq %r14, %rdi
callq 0x20a0
movq 0x8(%rsp), %rdi
callq 0x2040
callq 0x2070
xorl %eax, %eax
jmp 0x273f
movq %r14, %rdi
callq 0x2200
jmp 0x273a
addq $0x8, %r14
movq %r14, %rdi
callq 0x2317
jmp 0x273a
movq %rbx, %rdi
callq 0x22f4
jmp 0x273a
movq %r15, %rdi
movq %rbx, %rsi
callq 0x221e
jmp 0x273a
callq 0x224c
jmp 0x273a
callq 0x226e
jmp 0x273a
callq 0x22ce
jmp 0x273a
movq %rbx, %rdi
callq 0x2294
movl $0x1, %eax
addq $0x18a8, %rsp           # imm = 0x18A8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nopl (%rax)