#include #include #include #include #include #include #include #include #include #include #include #include #ifdef _WIN32 #include #else #include #include #include #endif static emu_context ctx; #ifdef __windows__ static HANDLE thread; #else static pthread_t thread; #endif emu_context *emu_get_context() { return &ctx; } #ifdef _WIN32 DWORD WINAPI cpu_run(void *p) { #else void *cpu_run(void *p) { #endif ctx.running = true; ctx.paused = false; ctx.ticks = 0; while (ctx.running) { //if (ctx.paused) { // delay(10); // continue; //} if (!cpu_step()) { printf("CPU stopped\n"); return 0; } } return 0; } void sleep_ms(int milis) { #ifdef _WIN32 Sleep(milis); #else usleep(milis * 1000); #endif } void emu_stop() { ctx.running = false; #ifdef __windows__ WaitForSingleObject(thread, INFINITE); #else pthread_join(thread, NULL); #endif } void emu_reset() { ppu_init(); timer_init(); cpu_init(); audio_init(); cart_init(); serial_init(); } void emu_start() { #ifdef __windows__ thread = CreateThread(NULL, 0, cpu_run, NULL, 0, NULL); #else pthread_create(&thread, NULL, cpu_run, NULL); #endif if(!thread) { fprintf(stderr, "Unable to create main CPU thread!\n"); } } int emu_run(int argc, char **argv) { if (argc < 2) { printf("Usage: gbemu \n"); return -1; } if(!cart_load(argv[1])) { printf("Failed to load ROM file: %s\n", argv[1]); return -2; } char fn[1048]; #ifdef __windows__ char *profile = getenv("USERPROFILE"); sprintf(fn, "%s\\Documents\\gbemu", profile); CreateDirectory(fn, NULL); sprintf(fn, "%s\\Documents\\gbemu\\saves", profile); CreateDirectory(fn, NULL); sprintf(fn, "%s\\Documents\\gbemu\\states", profile); CreateDirectory(fn, NULL); #else char *profile = getenv("HOME"); sprintf(fn, "%s/.config/gbemu", profile); mkdir(fn, 0755); sprintf(fn, "%s/.config/gbemu/saves", profile); mkdir(fn, 0755); sprintf(fn, "%s/.config/gbemu/states", profile); mkdir(fn, 0755); #endif printf("Cart loaded..\n"); ctx.app_path = argv[0]; ui_init(); emu_reset(); emu_start(); u32 prev_frame = 0; debug_init(); while(!ctx.die) { sleep_ms(1); ui_handle_events(); //if (prev_frame != ppu_get_context()->current_frame) { ui_update(); //} //prev_frame = ppu_get_context()->current_frame; if(ctx.debug) { debug_update(); } } return 0; } void emu_cycles(int cpu_cycles) { if(emu_get_context()->paused && !emu_get_context()->step) return; for (int i = 0; i < cpu_cycles; i++){ for(int n = 0; n < 4; n++){ ctx.ticks++; timer_tick(); ppu_tick(); } dma_tick(); } }