// File: /workspace/github_c_makefile_star2_O0/minkcv[P]vm/machine/vm.c
// Function: run
void run(VM* vm)
{
    uint32_t displayStartTime = SDL_GetTicks();
    uint32_t displayWaitTime = 16; // 16ms = about 60 refreshes per second
    uint32_t cpuStartTime = SDL_GetTicks();
    uint32_t cpuInstructionCount = 0;

    // Enforce the instructions per second limit in sync with the display refreshes
    // 500,000 instructions per second is almost the same as 8064 instructions per 16 milliseconds.
    // 500,000 IPS == 8000 instructions / 0.016 seconds
    // 500,000 / 8064 = 62
    uint32_t instructionsPerSecondFactor = 62;

    int wait = 0;
    SDL_Event event;
    SDL_PollEvent(&event);
    Instruction decoded;
    while (event.type != SDL_QUIT)
    {
        while (SDL_PollEvent(&event))
        {
            if (event.key.keysym.sym == SDLK_ESCAPE && event.type == SDL_KEYUP)
            {
                printf("Exiting at user escape\n");
                exit(0);
            }
            if (vm->cpu.debugMode && event.type == SDL_KEYUP)
            {
                handleDebugKey(vm, event.key.keysym.sym);
            }
            if (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP)
            {
                if (event.key.repeat == 0)
                {
                    updateIPU(vm->ipu, event.key, vm->memory);
                }
            }
        }

        if (vm->cpu.breakState)
            continue;

        // Executing
        if (!wait)
        {
            uint16_t instr = retro_le_to_cpu16(*(vm->cpu.pc));
            decode(instr, &decoded);
            exec(&vm->cpu, &decoded, vm->memory);
            vm->cpu.pc++;
            cpuInstructionCount++;

            if (cpuInstructionCount > INSTRUCTIONS_PER_SECOND / instructionsPerSecondFactor)
                // We have done 8064 instructions in this segment of 16 milliseconds. Don't do any more until the 16ms have passed.
                wait = 1;
        }
        if ((SDL_GetTicks() - cpuStartTime) > 1000 / instructionsPerSecondFactor)
        {
            // 16 milliseconds have passed
            // Reset the instruction count and timer
            if (cpuInstructionCount < INSTRUCTIONS_PER_SECOND / instructionsPerSecondFactor)
            {
                //printf("Running below desired instructions per second\n");
                //printf("Desired: %d Actual: %d\n", INSTRUCTIONS_PER_SECOND / instructionsPerSecondFactor, cpuInstructionCount);
            }
            cpuInstructionCount = 0;
            cpuStartTime = SDL_GetTicks();
            wait = 0;
        }
        if (displayStartTime + displayWaitTime < SDL_GetTicks())
        {
            updateGPU(vm->gpu, vm->memory);
            if (vm->gpu->active)
            {
                readSpritesFromMem(vm->gpu, vm->memory);
                drawSprites(vm->gpu, vm->memory);
                updateDisplay(vm->display, vm->gpu);
            }
            displayStartTime = SDL_GetTicks();
        }
        if (vm->cpu.step)
            vm->cpu.breakState = 1;
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x8(%rbp)
callq 0x1130
movl %eax, -0xc(%rbp)
movl $0x10, -0x10(%rbp)
callq 0x1130
movl %eax, -0x14(%rbp)
movl $0x0, -0x18(%rbp)
movl $0x3e, -0x1c(%rbp)
movl $0x0, -0x20(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x10b0
cmpl $0x100, -0x58(%rbp)     # imm = 0x100
je 0x1be3
jmp 0x19a3
leaq -0x58(%rbp), %rdi
callq 0x10b0
cmpl $0x0, %eax
je 0x1a58
cmpl $0x1b, -0x44(%rbp)
jne 0x19d9
cmpl $0x301, -0x58(%rbp)     # imm = 0x301
jne 0x19d9
leaq 0x36fd(%rip), %rdi      # 0x50c8
movb $0x0, %al
callq 0x1040
xorl %edi, %edi
callq 0x1170
movq -0x8(%rbp), %rax
cmpl $0x0, 0x20(%rax)
je 0x19f8
cmpl $0x301, -0x58(%rbp)     # imm = 0x301
jne 0x19f8
movq -0x8(%rbp), %rdi
movl -0x44(%rbp), %esi
callq 0x1bf0
cmpl $0x300, -0x58(%rbp)     # imm = 0x300
je 0x1a0a
cmpl $0x301, -0x58(%rbp)     # imm = 0x301
jne 0x1a53
movzbl -0x4b(%rbp), %eax
cmpl $0x0, %eax
jne 0x1a51
movq -0x8(%rbp), %rax
movq 0x10038(%rax), %rdi
movq -0x8(%rbp), %rsi
addq $0x30, %rsi
leaq -0x58(%rbp), %rax
movq (%rax), %rcx
movq %rcx, (%rsp)
movq 0x8(%rax), %rcx
movq %rcx, 0x8(%rsp)
movq 0x10(%rax), %rcx
movq %rcx, 0x10(%rsp)
movq 0x18(%rax), %rax
movq %rax, 0x18(%rsp)
callq 0x2e40
jmp 0x1a53
jmp 0x19a3
movq -0x8(%rbp), %rax
cmpl $0x0, 0x24(%rax)
je 0x1a67
jmp 0x1994
cmpl $0x0, -0x20(%rbp)
jne 0x1ad9
movq -0x8(%rbp), %rax
movq 0x10(%rax), %rax
movw (%rax), %ax
movw %ax, -0x5e(%rbp)
leaq -0x5c(%rbp), %rsi
movzwl -0x5e(%rbp), %edi
callq 0x3530
movq -0x8(%rbp), %rdi
movq -0x8(%rbp), %rdx
addq $0x30, %rdx
leaq -0x5c(%rbp), %rsi
callq 0x35f0
movq -0x8(%rbp), %rax
movq 0x10(%rax), %rcx
addq $0x2, %rcx
movq %rcx, 0x10(%rax)
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
movl -0x18(%rbp), %eax
movl %eax, -0x64(%rbp)
movl $0x7a120, %eax          # imm = 0x7A120
xorl %edx, %edx
divl -0x1c(%rbp)
movl %eax, %ecx
movl -0x64(%rbp), %eax
cmpl %ecx, %eax
jbe 0x1ad7
movl $0x1, -0x20(%rbp)
jmp 0x1ad9
callq 0x1130
subl -0x14(%rbp), %eax
movl %eax, -0x68(%rbp)
movl $0x3e8, %eax            # imm = 0x3E8
xorl %edx, %edx
divl -0x1c(%rbp)
movl %eax, %ecx
movl -0x68(%rbp), %eax
cmpl %ecx, %eax
jbe 0x1b28
movl -0x18(%rbp), %eax
movl %eax, -0x6c(%rbp)
movl $0x7a120, %eax          # imm = 0x7A120
xorl %edx, %edx
divl -0x1c(%rbp)
movl %eax, %ecx
movl -0x6c(%rbp), %eax
cmpl %ecx, %eax
jae 0x1b12
jmp 0x1b12
movl $0x0, -0x18(%rbp)
callq 0x1130
movl %eax, -0x14(%rbp)
movl $0x0, -0x20(%rbp)
movl -0xc(%rbp), %eax
addl -0x10(%rbp), %eax
movl %eax, -0x70(%rbp)
callq 0x1130
movl %eax, %ecx
movl -0x70(%rbp), %eax
cmpl %ecx, %eax
jae 0x1bc9
movq -0x8(%rbp), %rax
movq 0x10030(%rax), %rdi
movq -0x8(%rbp), %rsi
addq $0x30, %rsi
callq 0x20b0
movq -0x8(%rbp), %rax
movq 0x10030(%rax), %rax
movb 0xc10(%rax), %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
je 0x1bc1
movq -0x8(%rbp), %rax
movq 0x10030(%rax), %rdi
movq -0x8(%rbp), %rsi
addq $0x30, %rsi
callq 0x2180
movq -0x8(%rbp), %rax
movq 0x10030(%rax), %rdi
movq -0x8(%rbp), %rsi
addq $0x30, %rsi
callq 0x2460
movq -0x8(%rbp), %rax
movq 0x10040(%rax), %rdi
movq -0x8(%rbp), %rax
movq 0x10030(%rax), %rsi
callq 0x1f30
callq 0x1130
movl %eax, -0xc(%rbp)
movq -0x8(%rbp), %rax
cmpl $0x0, 0x28(%rax)
je 0x1bde
movq -0x8(%rbp), %rax
movl $0x1, 0x24(%rax)
jmp 0x1994
addq $0x90, %rsp
popq %rbp
retq
nopl (%rax)