// File: /workspace/github_c_makefile_star2_O1/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 $0x18b8, %rsp           # imm = 0x18B8
movq %rsi, %r14
cmpl $0x2, %edi
jne 0x2701
movq 0x8(%r14), %rdi
leaq 0x1b86(%rip), %rsi      # 0x401a
callq 0x2170
testq %rax, %rax
je 0x270b
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 0x2719
movq %rax, %r15
movl $0x1, %esi
movq %rax, %rdi
movq %r14, %rdx
movq %rbx, %rcx
callq 0x21c0
cmpq %r14, %rax
jne 0x2723
movq %rbx, %rdi
callq 0x2150
leaq 0x70(%rsp), %rbx
movl $0x1848, %edx           # imm = 0x1848
movq %rbx, %rdi
xorl %esi, %esi
callq 0x20c0
movq %rbx, %rdi
callq 0x2764
movq %rbx, %rdi
movq %r15, %rsi
movq %r14, %rdx
callq 0x27be
movl %eax, %ebx
movq %r15, %rdi
callq 0x2180
testl %ebx, %ebx
jne 0x2730
movl $0x20, %edi
callq 0x2110
testl %eax, %eax
jne 0x2737
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 0x273e
movq %rax, %rbx
movq %rax, %rdi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl $0x2, %edx
callq 0x2050
movq %rax, 0x8(%rsp)
testq %rax, %rax
je 0x2745
movq %rbx, 0x18(%rsp)
movb $0x1, %r15b
leaq 0x30(%rsp), %rbx
leaq 0x70(%rsp), %r12
xorl %r14d, %r14d
testb $0x1, %r15b
je 0x26e4
xorps %xmm0, %xmm0
movaps %xmm0, 0x50(%rsp)
movaps %xmm0, 0x40(%rsp)
movaps %xmm0, 0x30(%rsp)
movq $0x0, 0x60(%rsp)
movq %rbx, %rdi
callq 0x20d0
testl %eax, %eax
je 0x2612
movl 0x30(%rsp), %eax
movl 0x44(%rsp), %ecx
movl %eax, %edx
xorl $0x301, %edx            # imm = 0x301
xorl $0x1b, %ecx
orl %edx, %ecx
movzbl %r15b, %r15d
cmovel %r14d, %r15d
cmpl $0x100, %eax            # imm = 0x100
cmovel %r14d, %r15d
jmp 0x25de
movq %r12, %rdi
callq 0x280d
testl %eax, %eax
je 0x2626
xorl %r15d, %r15d
jmp 0x26dc
movl %eax, 0x14(%rsp)
movq 0x8(%rsp), %rbx
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
xorl %ecx, %ecx
movl $0xff, %r8d
callq 0x21a0
movq %rbx, %rdi
callq 0x2130
movq %rbx, %rdi
movl $0xff, %esi
movl $0xff, %edx
movl $0xff, %ecx
movl $0xff, %r8d
callq 0x21a0
xorl %ebx, %ebx
movl %ebx, %r13d
shll $0x4, %r13d
xorl %r14d, %r14d
xorl %ebp, %ebp
movq %r12, %rdi
movq %rbp, %rsi
movq %rbx, %rdx
callq 0x2896
testb %al, %al
je 0x26b0
movl %r14d, 0x20(%rsp)
movl %r13d, 0x24(%rsp)
movabsq $0x1000000010, %rax     # imm = 0x1000000010
movq %rax, 0x28(%rsp)
movq 0x8(%rsp), %rdi
leaq 0x20(%rsp), %rsi
callq 0x20b0
incq %rbp
addl $0x10, %r14d
cmpq $0x40, %rbp
jne 0x2676
incq %rbx
cmpq $0x20, %rbx
jne 0x266a
movq 0x8(%rsp), %rdi
callq 0x2080
leaq 0x30(%rsp), %rbx
xorl %r14d, %r14d
movl 0x14(%rsp), %eax
testl %eax, %eax
je 0x25b9
movq 0x8(%rsp), %rdi
callq 0x20a0
movq 0x18(%rsp), %rdi
callq 0x2040
callq 0x2070
xorl %eax, %eax
jmp 0x2752
movq %r14, %rdi
callq 0x2200
jmp 0x274d
addq $0x8, %r14
movq %r14, %rdi
callq 0x2317
jmp 0x274d
movq %rbx, %rdi
callq 0x22f4
jmp 0x274d
movq %r15, %rdi
movq %rbx, %rsi
callq 0x221e
jmp 0x274d
callq 0x224c
jmp 0x274d
callq 0x226e
jmp 0x274d
callq 0x22ce
jmp 0x274d
movq %rbx, %rdi
callq 0x2294
movl $0x1, %eax
addq $0x18b8, %rsp           # imm = 0x18B8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq