// File: /workspace/github_c_makefile_star2_O2/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 0x2556
movq 0x8(%r14), %rdi
leaq 0xd06(%rip), %rsi       # 0x301a
callq 0x2170
testq %rax, %rax
je 0x256f
movq %rax, %rbx
pushq $0x2
popq %rdx
movq %rax, %rdi
xorl %esi, %esi
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 0x2589
movq %rax, %r15
pushq $0x1
popq %rsi
movq %rax, %rdi
movq %r14, %rdx
movq %rbx, %rcx
callq 0x21c0
cmpq %r14, %rax
jne 0x25a6
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 0x2668
movq %rbx, %rdi
movq %r15, %rsi
movq %r14, %rdx
callq 0x26be
movl %eax, %ebx
movq %r15, %rdi
callq 0x2180
testl %ebx, %ebx
jne 0x25cb
pushq $0x20
popq %rdi
callq 0x2110
testl %eax, %eax
jne 0x25e9
leaq 0xceb(%rip), %rdi       # 0x30bd
pushq $0x20
popq %r9
movl $0x1fff0000, %esi       # imm = 0x1FFF0000
movl $0x1fff0000, %edx       # imm = 0x1FFF0000
movl $0x400, %ecx            # imm = 0x400
movl $0x200, %r8d            # imm = 0x200
callq 0x2060
testq %rax, %rax
je 0x2601
movq %rax, %r15
pushq $-0x1
popq %rsi
pushq $0x2
popq %rdx
movq %rax, %rdi
callq 0x2050
testq %rax, %rax
je 0x2639
movq %rax, %r14
movq %r15, 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)
andq $0x0, 0x50(%rsp)
movb $0x1, %bpl
movq %rbx, %rdi
callq 0x20d0
testl %eax, %eax
je 0x2472
movl 0x20(%rsp), %eax
movl 0x34(%rsp), %ecx
cmpl $0x100, %eax            # imm = 0x100
setne %dl
xorl $0x301, %eax            # imm = 0x301
xorl $0x1b, %ecx
orl %eax, %ecx
setne %al
andb %bpl, %dl
andb %al, %dl
movl %edx, %ebp
jmp 0x2440
movq %r12, %rdi
callq 0x270b
testl %eax, %eax
jne 0x2538
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
cmpq $0x20, %rbp
je 0x2520
movl %ebp, %r15d
shll $0x4, %r15d
xorl %r13d, %r13d
xorl %ebx, %ebx
cmpq $0x40, %rbx
je 0x251b
movq %r12, %rdi
movq %rbx, %rsi
movq %rbp, %rdx
callq 0x27be
testb %al, %al
je 0x2512
movl %r13d, 0x10(%rsp)
movl %r15d, 0x14(%rsp)
movabsq $0x1000000010, %rax     # imm = 0x1000000010
movq %rax, 0x18(%rsp)
movq %r14, %rdi
leaq 0x10(%rsp), %rsi
callq 0x20b0
incq %rbx
addl $0x10, %r13d
jmp 0x24d4
incq %rbp
jmp 0x24c2
movq %r14, %rdi
callq 0x2080
testb $0x1, 0x7(%rsp)
leaq 0x20(%rsp), %rbx
jne 0x2425
movq %r14, %rdi
callq 0x20a0
movq 0x8(%rsp), %rdi
callq 0x2040
callq 0x2070
xorl %eax, %eax
jmp 0x2627
movq 0x3a83(%rip), %rax      # 0x5fe0
movq (%rax), %rdi
movq (%r14), %rdx
leaq 0xa9a(%rip), %rsi       # 0x3004
jmp 0x261d
movq 0x3a6a(%rip), %rax      # 0x5fe0
movq (%rax), %rdi
movq 0x8(%r14), %rdx
leaq 0xa99(%rip), %rsi       # 0x301d
jmp 0x261d
movq %rbx, %rdi
callq 0x2150
movq 0x3a48(%rip), %rax      # 0x5fe0
movq (%rax), %rcx
leaq 0xa93(%rip), %rdi       # 0x3035
pushq $0x2f
jmp 0x25de
movq %r15, %rdi
callq 0x2180
movq %rbx, %rdi
callq 0x2150
movq 0x3a23(%rip), %rax      # 0x5fe0
movq (%rax), %rcx
leaq 0xa9e(%rip), %rdi       # 0x3065
pushq $0x1f
jmp 0x25de
movq 0x3a0e(%rip), %rax      # 0x5fe0
movq (%rax), %rcx
leaq 0xaa9(%rip), %rdi       # 0x3085
pushq $0x1e
popq %rsi
pushq $0x1
popq %rdx
callq 0x21e0
jmp 0x2624
movq 0x39f0(%rip), %rax      # 0x5fe0
movq (%rax), %rbx
callq 0x20f0
leaq 0xaa5(%rip), %rsi       # 0x30a4
jmp 0x2617
movq 0x39d8(%rip), %rax      # 0x5fe0
movq (%rax), %rbx
callq 0x20f0
leaq 0xabe(%rip), %rsi       # 0x30d5
movq %rbx, %rdi
movq %rax, %rdx
xorl %eax, %eax
callq 0x21b0
pushq $0x1
popq %rax
addq $0x18a8, %rsp           # imm = 0x18A8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x39a0(%rip), %rax      # 0x5fe0
movq (%rax), %rbx
callq 0x20f0
leaq 0xaa8(%rip), %rsi       # 0x30f7
movq %rbx, %rdi
movq %rax, %rdx
xorl %eax, %eax
callq 0x21b0
movq %r15, %rdi
callq 0x2040
jmp 0x2624
nop