src/platform/sdl/main.c (view raw)
1#include "main.h"
2
3#ifdef USE_CLI_DEBUGGER
4#include "debugger/cli-debugger.h"
5#endif
6
7#ifdef USE_GDB_STUB
8#include "debugger/gdb-stub.h"
9#endif
10
11#include "gba-thread.h"
12#include "gba.h"
13#include "gba-config.h"
14#include "gba-video.h"
15#include "platform/commandline.h"
16#include "util/configuration.h"
17
18#include <SDL.h>
19
20#include <errno.h>
21#include <signal.h>
22#include <sys/time.h>
23
24#define PORT "sdl"
25
26static bool _GBASDLInit(struct SDLSoftwareRenderer* renderer);
27static void _GBASDLDeinit(struct SDLSoftwareRenderer* renderer);
28
29int main(int argc, char** argv) {
30 struct SDLSoftwareRenderer renderer;
31 GBAVideoSoftwareRendererCreate(&renderer.d);
32
33 struct GBAInputMap inputMap;
34 GBAInputMapInit(&inputMap);
35
36 struct GBAConfig config;
37 GBAConfigInit(&config, PORT);
38 GBAConfigLoad(&config);
39
40 struct GBAOptions opts = {
41 .width = VIDEO_HORIZONTAL_PIXELS,
42 .height = VIDEO_VERTICAL_PIXELS,
43 .audioBuffers = 512,
44 .videoSync = false,
45 .audioSync = true,
46 };
47 GBAConfigLoadDefaults(&config, &opts);
48
49 struct GBAArguments args = {};
50 struct GraphicsOpts graphicsOpts = {};
51
52 struct SubParser subparser;
53
54 initParserForGraphics(&subparser, &graphicsOpts);
55 if (!parseArguments(&args, &config, argc, argv, &subparser)) {
56 usage(argv[0], subparser.usage);
57 freeArguments(&args);
58 GBAConfigFreeOpts(&opts);
59 GBAConfigDeinit(&config);
60 return 1;
61 }
62
63 GBAConfigMap(&config, &opts);
64
65 renderer.viewportWidth = opts.width;
66 renderer.viewportHeight = opts.height;
67#if SDL_VERSION_ATLEAST(2, 0, 0)
68 renderer.events.fullscreen = opts.fullscreen;
69 renderer.events.windowUpdated = 0;
70#endif
71 renderer.ratio = graphicsOpts.multiplier;
72
73 if (!_GBASDLInit(&renderer)) {
74 freeArguments(&args);
75 GBAConfigFreeOpts(&opts);
76 GBAConfigDeinit(&config);
77 return 1;
78 }
79
80 struct GBAThread context = {
81 .renderer = &renderer.d.d,
82 .userData = &renderer
83 };
84
85 context.debugger = createDebugger(&args, &context);
86
87 GBAMapOptionsToContext(&opts, &context);
88 GBAMapArgumentsToContext(&args, &context);
89
90 renderer.audio.samples = context.audioBuffers;
91 GBASDLInitAudio(&renderer.audio, &context);
92
93 renderer.events.bindings = &inputMap;
94 GBASDLInitBindings(&inputMap);
95 GBASDLInitEvents(&renderer.events);
96 GBASDLEventsLoadConfig(&renderer.events, &config.configTable); // TODO: Don't use this directly
97
98 GBAThreadStart(&context);
99
100 GBASDLRunloop(&context, &renderer);
101
102 GBAThreadJoin(&context);
103 freeArguments(&args);
104 GBAConfigFreeOpts(&opts);
105 GBAConfigDeinit(&config);
106 free(context.debugger);
107 GBAInputMapDeinit(&inputMap);
108
109 _GBASDLDeinit(&renderer);
110
111 return 0;
112}
113
114static bool _GBASDLInit(struct SDLSoftwareRenderer* renderer) {
115 if (SDL_Init(SDL_INIT_VIDEO) < 0) {
116 return false;
117 }
118
119 return GBASDLInit(renderer);
120}
121
122static void _GBASDLDeinit(struct SDLSoftwareRenderer* renderer) {
123 free(renderer->d.outputBuffer);
124
125 GBASDLDeinitEvents(&renderer->events);
126 GBASDLDeinitAudio(&renderer->audio);
127#if SDL_VERSION_ATLEAST(2, 0, 0)
128 SDL_DestroyWindow(renderer->window);
129#endif
130
131 GBASDLDeinit(renderer);
132
133 SDL_Quit();
134
135}