all repos — mgba @ be36c1b5d66095dd33d635a4761ab9c589c545c6

mGBA Game Boy Advance Emulator

src/gba/gba-thread.c (view raw)

  1#include "gba-thread.h"
  2
  3#include "arm.h"
  4#include "debugger.h"
  5#include "gba.h"
  6
  7#include <stdlib.h>
  8#include <signal.h>
  9
 10static void* _GBAThreadRun(void* context) {
 11	struct ARMDebugger debugger;
 12	struct GBA gba;
 13	struct GBAThread* threadContext = context;
 14	char* savedata = 0;
 15
 16	sigset_t signals;
 17	sigfillset(&signals);
 18	pthread_sigmask(SIG_UNBLOCK, &signals, 0);
 19
 20	GBAInit(&gba);
 21	if (threadContext->renderer) {
 22		GBAVideoAssociateRenderer(&gba.video, threadContext->renderer);
 23	}
 24
 25	threadContext->gba = &gba;
 26	if (threadContext->fd >= 0) {
 27		if (threadContext->fname) {
 28			char* dotPoint = strrchr(threadContext->fname, '.');
 29			if (dotPoint > strrchr(threadContext->fname, '/') && dotPoint[1] && dotPoint[2] && dotPoint[3]) {
 30				savedata = strdup(threadContext->fname);
 31				dotPoint = strrchr(savedata, '.');
 32				dotPoint[1] = 's';
 33				dotPoint[2] = 'a';
 34				dotPoint[3] = 'v';
 35				dotPoint[4] = '\0';
 36			} else if (dotPoint) {
 37				savedata = malloc((dotPoint - threadContext->fname + 5) * sizeof(char));
 38				strncpy(savedata, threadContext->fname, dotPoint - threadContext->fname + 1);
 39				strcat(savedata, "sav");
 40			} else {
 41				savedata = malloc(strlen(threadContext->fname + 5));
 42				strcpy(savedata, threadContext->fname);
 43				strcat(savedata, "sav");
 44			}
 45		}
 46		GBALoadROM(&gba, threadContext->fd, threadContext->fname);
 47		gba.savefile = savedata;
 48	}
 49	if (threadContext->useDebugger) {
 50		threadContext->debugger = &debugger;
 51		GBAAttachDebugger(&gba, &debugger);
 52	} else {
 53		threadContext->debugger = 0;
 54	}
 55	gba.keySource = &threadContext->activeKeys;
 56
 57	threadContext->started = 1;
 58	pthread_mutex_lock(&threadContext->mutex);
 59	pthread_cond_broadcast(&threadContext->cond);
 60	pthread_mutex_unlock(&threadContext->mutex);
 61
 62	if (threadContext->useDebugger) {
 63		ARMDebuggerRun(&debugger);
 64		threadContext->started = 0;
 65	} else {
 66		while (threadContext->started) {
 67			ARMRun(&gba.cpu);
 68		}
 69	}
 70	GBADeinit(&gba);
 71	free(savedata);
 72
 73	return 0;
 74}
 75
 76int GBAThreadStart(struct GBAThread* threadContext) {
 77	// TODO: error check
 78	{
 79		pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
 80		threadContext->mutex = mutex;
 81		pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
 82		threadContext->cond = cond;
 83	}
 84	pthread_mutex_init(&threadContext->mutex, 0);
 85	pthread_cond_init(&threadContext->cond, 0);
 86
 87	pthread_mutex_lock(&threadContext->mutex);
 88	threadContext->activeKeys = 0;
 89	threadContext->started = 0;
 90	pthread_create(&threadContext->thread, 0, _GBAThreadRun, threadContext);
 91	pthread_cond_wait(&threadContext->cond, &threadContext->mutex);
 92	pthread_mutex_unlock(&threadContext->mutex);
 93
 94	return 0;
 95}
 96
 97void GBAThreadJoin(struct GBAThread* threadContext) {
 98	pthread_join(threadContext->thread, 0);
 99
100	pthread_mutex_destroy(&threadContext->mutex);
101	pthread_cond_destroy(&threadContext->cond);
102}