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}