Files
gbemu/lib/emu.c
2025-06-13 15:33:13 -06:00

164 lines
3.1 KiB
C

#include <emu.h>
#include <stdio.h>
#include <cart.h>
#include <cpu.h>
#include <ui.h>
#include <timer.h>
#include <dma.h>
#include <ppu.h>
#include <audio.h>
#include <cart.h>
#include <debug.h>
#include <serial.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <pthread.h>
#include <unistd.h>
#include <sys/stat.h>
#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 <rom_file>\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();
}
}