all repos — mgba @ 7cdcdbd7b4631485e6c1acd00535e8f3c1151293

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