Example #1
0
uint8_t execute_interpreter_cycle(cpu_registers* registers, bool nmi_flag) {
    static bool previous_nmi_flag = false;
    uint8_t cpu_cycles_executed = 0;
    uint8_t extra_cycles= 0;

    if(DMA_is_executing()) cpu_cycles_executed = execute_DMA();
    else {
        uint8_t opcode = fetch_opcode(registers);
        increment_PC(registers);

        if(nmi_flag && !previous_nmi_flag) cpu_cycles_executed = execute_NMI(registers);
        else {
            #ifdef DEBUG
                print_debug_info(registers, opcode);
            #endif
            extra_cycles = execute_instruction(registers, opcode);
            cpu_cycles_executed = instruction_cycle_length[opcode] + extra_cycles;
            // Do not increment PC if we jump because it will skip the first instruction at least
            if(!is_JSR_or_JMP(opcode) && !is_RTI(opcode)) increment_PC_instruction_length(registers, opcode);
        }
    }

    previous_nmi_flag = nmi_flag;
    odd_cpu_cycle = cpu_cycles_executed & 0x1;

    return cpu_cycles_executed;
}
void execute_loop(chip_8_cpu cpu, FILE *debug_log) {
    if (pthread_create(&(cpu->delay_decrement_thread), NULL, delay_thread, cpu) != 0) {
        shutdown_cpu(cpu, 1);
    }
    if (pthread_create(&(cpu->sound_decrement_thread), NULL, sound_thread, cpu) != 0) {
        fprintf(stderr, "Failed to start the sound register thread, exiting...\n");
        shutdown_cpu(cpu, 1);
    }
    pthread_detach(cpu->delay_decrement_thread);
    pthread_detach(cpu->sound_decrement_thread);

    cpu->chip_8_screen = init_ncurses(default_window_height, default_window_width);
    refresh_window(cpu->chip_8_screen);

    while (1) {
        if (cpu->program_counter >= MEMORY_SIZE) {
            fprintf(stderr, "ERR - Fatal memory error: invalid access at memory cell: '%d'\n", cpu->program_counter);
            shutdown_cpu(cpu, 1);
        }
        if (cpu->halt) {
            break;
        }
        opcode instr = fetch_opcode(cpu);
        if (debug_log) {
            print_debug_info(debug_log, instr, cpu);
        }

        execute_opcode(instr, cpu);
        if (cpu->performed_jump) {
            cpu->performed_jump = false;
            continue;
        }

        if (cpu->skip_opcode) {
            cpu->program_counter = cpu->program_counter + 2;
            cpu->skip_opcode = false;
        }
        else {
            cpu->program_counter = cpu->program_counter + 1;
        }
    }

    // allow 0.1 seconds for the threads to clean up their memory
    usleep(100000);
    delwin(cpu->chip_8_screen);
    endwin();
}