src/platform/sdl/sw-main.c (view raw)
1#include "debugger/debugger.h"
2#include "gba-thread.h"
3#include "gba.h"
4#include "renderers/video-software.h"
5#include "sdl-audio.h"
6#include "sdl-events.h"
7
8#include <SDL.h>
9
10#include <fcntl.h>
11#include <errno.h>
12#include <signal.h>
13#include <sys/time.h>
14
15struct SoftwareRenderer {
16 struct GBAVideoSoftwareRenderer d;
17 struct GBASDLAudio audio;
18 struct GBASDLEvents events;
19};
20
21static int _GBASDLInit(struct SoftwareRenderer* renderer);
22static void _GBASDLDeinit(struct SoftwareRenderer* renderer);
23static void _GBASDLRunloop(struct GBAThread* context);
24static void _GBASDLStart(struct GBAThread* context);
25static void _GBASDLClean(struct GBAThread* context);
26
27int main(int argc, char** argv) {
28 const char* fname = "test.rom";
29 if (argc > 1) {
30 fname = argv[1];
31 }
32 int fd = open(fname, O_RDONLY);
33 if (fd < 0) {
34 return 1;
35 }
36
37 struct GBAThread context;
38 struct SoftwareRenderer renderer;
39 GBAVideoSoftwareRendererCreate(&renderer.d);
40
41 if (!_GBASDLInit(&renderer)) {
42 return 1;
43 }
44
45 context.fd = fd;
46 context.fname = fname;
47 context.useDebugger = 1;
48 context.renderer = &renderer.d.d;
49 context.frameskip = 0;
50 context.sync.videoFrameWait = 0;
51 context.sync.audioWait = 1;
52 context.startCallback = _GBASDLStart;
53 context.cleanCallback = _GBASDLClean;
54 context.userData = &renderer;
55
56 SDL_Surface* surface = SDL_GetVideoSurface();
57 SDL_LockSurface(surface);
58 renderer.d.outputBuffer = surface->pixels;
59#ifdef COLOR_16_BIT
60 renderer.d.outputBufferStride = surface->pitch / 2;
61#else
62 renderer.d.outputBufferStride = surface->pitch / 4;
63#endif
64
65 GBAThreadStart(&context);
66
67 _GBASDLRunloop(&context);
68
69 SDL_UnlockSurface(surface);
70 GBAThreadJoin(&context);
71 close(fd);
72
73 _GBASDLDeinit(&renderer);
74
75 return 0;
76}
77
78static int _GBASDLInit(struct SoftwareRenderer* renderer) {
79 if (SDL_Init(SDL_INIT_VIDEO) < 0) {
80 return 0;
81 }
82
83 GBASDLInitEvents(&renderer->events);
84 GBASDLInitAudio(&renderer->audio);
85
86#ifdef COLOR_16_BIT
87 SDL_SetVideoMode(240, 160, 16, SDL_DOUBLEBUF | SDL_HWSURFACE);
88#else
89 SDL_SetVideoMode(240, 160, 32, SDL_DOUBLEBUF | SDL_HWSURFACE);
90#endif
91
92 return 1;
93}
94
95static void _GBASDLRunloop(struct GBAThread* context) {
96 SDL_Event event;
97 SDL_Surface* surface = SDL_GetVideoSurface();
98
99 while (context->state < THREAD_EXITING) {
100 if (GBASyncWaitFrameStart(&context->sync, context->frameskip)) {
101 SDL_UnlockSurface(surface);
102 SDL_Flip(surface);
103 SDL_LockSurface(surface);
104 }
105 GBASyncWaitFrameEnd(&context->sync);
106
107 while (SDL_PollEvent(&event)) {
108 GBASDLHandleEvent(context, &event);
109 }
110 }
111}
112
113static void _GBASDLDeinit(struct SoftwareRenderer* renderer) {
114 GBASDLDeinitEvents(&renderer->events);
115 GBASDLDeinitAudio(&renderer->audio);
116 SDL_Quit();
117}
118
119static void _GBASDLStart(struct GBAThread* threadContext) {
120 struct SoftwareRenderer* renderer = threadContext->userData;
121 renderer->audio.audio = &threadContext->gba->audio;
122}
123
124static void _GBASDLClean(struct GBAThread* threadContext) {
125 struct SoftwareRenderer* renderer = threadContext->userData;
126 renderer->audio.audio = 0;
127}