all repos — mgba @ 8607275f9f60372a8c551f7b9d77e460416c0183

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