all repos — mgba @ 25f5520b0b59a5235dae0c9c476baa9e2753269f

mGBA Game Boy Advance Emulator

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