1 |
/* |
2 |
* PearPC |
3 |
* syssdl.cc |
4 |
* |
5 |
* Copyright (C) 2004 Jens v.d. Heydt (mailme@vdh-webservice.de) |
6 |
* Copyright (C) 1999-2002 Stefan Weyergraf |
7 |
* Copyright (C) 1999-2004 Sebastian Biallas (sb@biallas.net) |
8 |
* |
9 |
* This program is free software; you can redistribute it and/or modify |
10 |
* it under the terms of the GNU General Public License version 2 as |
11 |
* published by the Free Software Foundation. |
12 |
* |
13 |
* This program is distributed in the hope that it will be useful, |
14 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 |
* GNU General Public License for more details. |
17 |
* |
18 |
* You should have received a copy of the GNU General Public License |
19 |
* along with this program; if not, write to the Free Software |
20 |
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
21 |
*/ |
22 |
|
23 |
#include <SDL.h> |
24 |
#include <SDL_thread.h> |
25 |
|
26 |
#include <csignal> |
27 |
#include <cstdlib> |
28 |
#include <cstdio> |
29 |
#include <unistd.h> |
30 |
#include <cstring> |
31 |
|
32 |
// for stopping the CPU |
33 |
#include "cpu/cpu.h" |
34 |
|
35 |
#include "system/sysclk.h" |
36 |
#include "system/display.h" |
37 |
#include "system/keyboard.h" |
38 |
#include "system/mouse.h" |
39 |
#include "system/systhread.h" |
40 |
#include "system/systimer.h" |
41 |
|
42 |
#include "tools/snprintf.h" |
43 |
|
44 |
#include "syssdl.h" |
45 |
|
46 |
SDL_Surface * gSDLScreen; |
47 |
static bool gSDLVideoExposePending = false; |
48 |
SDL_TimerID SDL_RedrawTimerID; |
49 |
|
50 |
SDLSystemDisplay *sd; |
51 |
|
52 |
#if 0 |
53 |
|
54 |
// Argl, this doesn't work, stupid SDL |
55 |
|
56 |
static uint8 sdl_key_to_adb_key[512]; |
57 |
|
58 |
static struct { |
59 |
SDLKey sdlkey; |
60 |
uint8 adbkey; |
61 |
} sdladbkeys[] = { |
62 |
{SDLK_BACKSPACE, KEY_DELETE}, |
63 |
{SDLK_TAB, KEY_TAB}, |
64 |
{SDLK_RETURN, KEY_RETURN}, |
65 |
{SDLK_PAUSE, KEY_PAUSE}, |
66 |
{SDLK_ESCAPE, KEY_ESCAPE}, |
67 |
{SDLK_SPACE, KEY_SPACE}, |
68 |
{SDLK_COMMA, KEY_COMMA}, |
69 |
{SDLK_MINUS, KEY_MINUS}, |
70 |
{SDLK_PERIOD, KEY_PERIOD}, |
71 |
{SDLK_0, KEY_0}, |
72 |
{SDLK_1, KEY_1}, |
73 |
{SDLK_2, KEY_2}, |
74 |
{SDLK_3, KEY_3}, |
75 |
{SDLK_4, KEY_4}, |
76 |
{SDLK_5, KEY_5}, |
77 |
{SDLK_6, KEY_6}, |
78 |
{SDLK_7, KEY_7}, |
79 |
{SDLK_8, KEY_8}, |
80 |
{SDLK_9, KEY_9}, |
81 |
{SDLK_SEMICOLON, KEY_SEMICOLON}, |
82 |
{SDLK_LEFTBRACKET, KEY_BRACKET_R}, |
83 |
{SDLK_BACKSLASH, KEY_BACKSLASH}, |
84 |
{SDLK_RIGHTBRACKET, KEY_BRACKET_L}, |
85 |
{SDLK_BACKQUOTE, KEY_GRAVE}, |
86 |
{SDLK_a, KEY_a}, |
87 |
{SDLK_b, KEY_b}, |
88 |
{SDLK_c, KEY_c}, |
89 |
{SDLK_d, KEY_d}, |
90 |
{SDLK_e, KEY_e}, |
91 |
{SDLK_f, KEY_f}, |
92 |
{SDLK_g, KEY_g}, |
93 |
{SDLK_h, KEY_h}, |
94 |
{SDLK_i, KEY_i}, |
95 |
{SDLK_j, KEY_j}, |
96 |
{SDLK_k, KEY_k}, |
97 |
{SDLK_l, KEY_l}, |
98 |
{SDLK_m, KEY_m}, |
99 |
{SDLK_n, KEY_n}, |
100 |
{SDLK_o, KEY_o}, |
101 |
{SDLK_p, KEY_p}, |
102 |
{SDLK_q, KEY_q}, |
103 |
{SDLK_r, KEY_r}, |
104 |
{SDLK_s, KEY_s}, |
105 |
{SDLK_t, KEY_t}, |
106 |
{SDLK_u, KEY_u}, |
107 |
{SDLK_v, KEY_v}, |
108 |
{SDLK_w, KEY_w}, |
109 |
{SDLK_x, KEY_x}, |
110 |
{SDLK_y, KEY_y}, |
111 |
{SDLK_z, KEY_z}, |
112 |
{SDLK_DELETE, KEY_REMOVE}, |
113 |
{SDLK_KP0, KEY_KP_0}, |
114 |
{SDLK_KP1, KEY_KP_1}, |
115 |
{SDLK_KP2, KEY_KP_2}, |
116 |
{SDLK_KP3, KEY_KP_3}, |
117 |
{SDLK_KP4, KEY_KP_4}, |
118 |
{SDLK_KP5, KEY_KP_5}, |
119 |
{SDLK_KP6, KEY_KP_6}, |
120 |
{SDLK_KP7, KEY_KP_7}, |
121 |
{SDLK_KP8, KEY_KP_8}, |
122 |
{SDLK_KP9, KEY_KP_9}, |
123 |
{SDLK_KP_PERIOD, KEY_KP_PERIOD}, |
124 |
{SDLK_KP_DIVIDE, KEY_KP_DIVIDE}, |
125 |
{SDLK_KP_MULTIPLY, KEY_KP_MULTIPLY}, |
126 |
{SDLK_KP_MINUS, KEY_KP_SUBTRACT}, |
127 |
{SDLK_KP_PLUS, KEY_KP_ADD}, |
128 |
{SDLK_KP_ENTER, KEY_KP_ENTER}, |
129 |
{SDLK_UP, KEY_UP}, |
130 |
{SDLK_DOWN, KEY_DOWN}, |
131 |
{SDLK_RIGHT, KEY_RIGHT}, |
132 |
{SDLK_LEFT, KEY_LEFT}, |
133 |
{SDLK_INSERT, KEY_INSERT}, |
134 |
{SDLK_HOME, KEY_HOME}, |
135 |
{SDLK_END, KEY_END}, |
136 |
{SDLK_PAGEUP, KEY_PRIOR}, |
137 |
{SDLK_PAGEDOWN, KEY_NEXT}, |
138 |
{SDLK_F1, KEY_F1}, |
139 |
{SDLK_F2, KEY_F2}, |
140 |
{SDLK_F3, KEY_F3}, |
141 |
{SDLK_F4, KEY_F4}, |
142 |
{SDLK_F5, KEY_F5}, |
143 |
{SDLK_F6, KEY_F6}, |
144 |
{SDLK_F7, KEY_F7}, |
145 |
{SDLK_F8, KEY_F8}, |
146 |
{SDLK_F9, KEY_F9}, |
147 |
{SDLK_F10, KEY_F10}, |
148 |
{SDLK_F11, KEY_F11}, |
149 |
{SDLK_F12, KEY_F12}, |
150 |
{SDLK_F13, KEY_F13}, |
151 |
{SDLK_NUMLOCK, KEY_NUM_LOCK}, |
152 |
{SDLK_CAPSLOCK, KEY_CAPS_LOCK}, |
153 |
{SDLK_SCROLLOCK, KEY_SCROLL_LOCK}, |
154 |
{SDLK_RSHIFT, KEY_SHIFT}, |
155 |
{SDLK_LSHIFT, KEY_SHIFT}, |
156 |
{SDLK_RCTRL, KEY_CONTROL}, |
157 |
{SDLK_LCTRL, KEY_CONTROL}, |
158 |
{SDLK_RALT, KEY_ALTGR}, |
159 |
{SDLK_LALT, KEY_ALT}, |
160 |
}; |
161 |
|
162 |
static void createSDLToADBKeytable() |
163 |
{ |
164 |
memset(sdl_key_to_adb_key, 0xff, sizeof sdl_key_to_adb_key); |
165 |
for (uint i=0; i < (sizeof sdladbkeys / sizeof sdladbkeys[0]); i++) { |
166 |
if (sdladbkeys[i].sdlkey > sizeof sdl_key_to_adb_key) { |
167 |
ht_printf("%d > 256 for key %d\n", sdladbkeys[i].sdlkey, sdladbkeys[i].adbkey); |
168 |
} |
169 |
sdl_key_to_adb_key[sdladbkeys[i].sdlkey] = sdladbkeys[i].adbkey; |
170 |
} |
171 |
} |
172 |
|
173 |
#else |
174 |
|
175 |
#ifdef __WIN32__ |
176 |
static byte scancode_to_adb_key[] = { |
177 |
//00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |
178 |
0xff,0x35,0x12,0x13,0x14,0x15,0x17,0x16,0x1a,0x1c,0x19,0x1d,0x1b,0x18,0x33,0x30, |
179 |
0x0c,0x0d,0x0e,0x0f,0x11,0x10,0x20,0x22,0x1f,0x23,0x21,0x1e,0x24,0x36,0x00,0x01, |
180 |
0x02,0x03,0x05,0x04,0x26,0x28,0x25,0x29,0x27,0xff,0x38,0x2a,0x06,0x07,0x08,0x09, |
181 |
0x0b,0x2d,0x2e,0x2b,0x2f,0x2c,0x38,0x43,0x37,0x31,0x39,0x7a,0x78,0x63,0x76,0x60, |
182 |
0x61,0x62,0x64,0x65,0x6d,0xff,0xff,0x59,0x5b,0x5c,0x4e,0x56,0x57,0x58,0x45,0x53, |
183 |
0x54,0x55,0x52,0x41,0xff,0xff,0x0a,0x67,0x6f,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
184 |
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
185 |
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
186 |
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
187 |
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x36,0xff,0xff, |
188 |
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
189 |
0xff,0xff,0xff,0xff,0xff,0x4b,0xff,0xff,0x3a,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
190 |
0xff,0xff,0xff,0xff,0xff,0x71,0xff,0x73,0x3e,0x74,0xff,0x3b,0xff,0x3c,0xff,0x77, |
191 |
0x3d,0x79,0x72,0x75,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
192 |
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
193 |
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
194 |
}; |
195 |
|
196 |
#else |
197 |
|
198 |
static uint8 scancode_to_adb_key[256] = { |
199 |
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
200 |
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x35,0x12,0x13,0x14,0x15,0x17,0x16, |
201 |
0x1a,0x1c,0x19,0x1d,0x1b,0x18,0x33,0x30,0x0c,0x0d,0x0e,0x0f,0x11,0x10,0x20,0x22, |
202 |
0x1f,0x23,0x21,0x1e,0x24,0x36,0x00,0x01,0x02,0x03,0x05,0x04,0x26,0x28,0x25,0x29, |
203 |
0x27,0x32,0x38,0x2a,0x06,0x07,0x08,0x09,0x0b,0x2d,0x2e,0x2b,0x2f,0x2c,0x38,0x43, |
204 |
0x37,0x31,0xff,0x7a,0x78,0x63,0x76,0x60,0x61,0x62,0x64,0x65,0x6d,0x47,0xff,0x59, |
205 |
0x5b,0x5c,0x4e,0x56,0x57,0x58,0x45,0x53,0x54,0x55,0x52,0x41,0xff,0xff,0x0a,0x67, |
206 |
0x6f,0x73,0x3e,0x74,0x3b,0xff,0x3c,0x77,0x3d,0x79,0x72,0x75,0x4c,0x36,0xff,0xff, |
207 |
0x4b,0x3a,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
208 |
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
209 |
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
210 |
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
211 |
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
212 |
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
213 |
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
214 |
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
215 |
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
216 |
}; |
217 |
|
218 |
#endif |
219 |
|
220 |
#endif |
221 |
|
222 |
static bool handleSDLEvent(const SDL_Event &event) |
223 |
{ |
224 |
static bool mouseButton[3] = {false, false, false}; |
225 |
bool tmpMouseButton[3]; |
226 |
|
227 |
SystemEvent ev; |
228 |
switch (event.type) { |
229 |
case SDL_USEREVENT: |
230 |
if (event.user.code == 1) { // helper for changeResolution |
231 |
//ht_printf("got forward event\n"); |
232 |
sd->mChangeResRet = sd->changeResolutionREAL(sd->mSDLChartemp); |
233 |
SDL_CondSignal(sd->mWaitcondition); // Signal, that condition is over. |
234 |
} |
235 |
return true; |
236 |
case SDL_VIDEOEXPOSE: |
237 |
gDisplay->displayShow(); |
238 |
gSDLVideoExposePending = false; |
239 |
return true; |
240 |
case SDL_KEYUP: |
241 |
ev.key.keycode = scancode_to_adb_key[event.key.keysym.scancode]; |
242 |
// ht_printf("%x %x up ", event.key.keysym.scancode, ev.key.keycode); |
243 |
if ((ev.key.keycode & 0xff) == 0xff) break; |
244 |
ev.type = sysevKey; |
245 |
ev.key.pressed = false; |
246 |
gKeyboard->handleEvent(ev); |
247 |
return true; |
248 |
case SDL_KEYDOWN: |
249 |
ev.key.keycode = scancode_to_adb_key[event.key.keysym.scancode]; |
250 |
// ht_printf("%x %x %x dn \n", event.key.keysym.sym, event.key.keysym.scancode, ev.key.keycode); |
251 |
if ((ev.key.keycode & 0xff) == 0xff) break; |
252 |
ev.type = sysevKey; |
253 |
ev.key.pressed = true; |
254 |
gKeyboard->handleEvent(ev); |
255 |
return true; |
256 |
case SDL_MOUSEBUTTONDOWN: |
257 |
ev.type = sysevMouse; |
258 |
ev.mouse.type = sme_buttonPressed; |
259 |
memcpy(tmpMouseButton, mouseButton, sizeof (tmpMouseButton)); |
260 |
mouseButton[0] = SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(1); |
261 |
mouseButton[1] = SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(2); |
262 |
mouseButton[2] = SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(3); |
263 |
ev.mouse.button1 = mouseButton[0]; |
264 |
ev.mouse.button2 = mouseButton[1]; |
265 |
ev.mouse.button3 = mouseButton[2]; |
266 |
if (mouseButton[0] != tmpMouseButton[0]) { |
267 |
ev.mouse.dbutton = 1; |
268 |
} else if (mouseButton[1] != tmpMouseButton[1]) { |
269 |
ev.mouse.dbutton = 2; |
270 |
} else if (mouseButton[2] != tmpMouseButton[2]) { |
271 |
ev.mouse.dbutton = 3; |
272 |
} else { |
273 |
ev.mouse.dbutton = 0; |
274 |
} |
275 |
ev.mouse.x = gDisplay->mCurMouseX; |
276 |
ev.mouse.y = gDisplay->mCurMouseY; |
277 |
ev.mouse.relx = 0; |
278 |
ev.mouse.rely = 0; |
279 |
gMouse->handleEvent(ev); |
280 |
return true; |
281 |
case SDL_MOUSEBUTTONUP: |
282 |
ev.type = sysevMouse; |
283 |
ev.mouse.type = sme_buttonReleased; |
284 |
memcpy(tmpMouseButton, mouseButton, sizeof (tmpMouseButton)); |
285 |
mouseButton[0] = SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(1); |
286 |
mouseButton[1] = SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(2); |
287 |
mouseButton[2] = SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(3); |
288 |
ev.mouse.button1 = mouseButton[0]; |
289 |
ev.mouse.button2 = mouseButton[1]; |
290 |
ev.mouse.button3 = mouseButton[2]; |
291 |
if (mouseButton[0] != tmpMouseButton[0]) { |
292 |
ev.mouse.dbutton = 1; |
293 |
} else if (mouseButton[1] != tmpMouseButton[1]) { |
294 |
ev.mouse.dbutton = 2; |
295 |
} else if (mouseButton[2] != tmpMouseButton[2]) { |
296 |
ev.mouse.dbutton = 3; |
297 |
} else { |
298 |
ev.mouse.dbutton = 0; |
299 |
} |
300 |
ev.mouse.x = gDisplay->mCurMouseX; |
301 |
ev.mouse.y = gDisplay->mCurMouseY; |
302 |
ev.mouse.relx = 0; |
303 |
ev.mouse.rely = 0; |
304 |
gMouse->handleEvent(ev); |
305 |
return true; |
306 |
case SDL_MOUSEMOTION: |
307 |
ev.type = sysevMouse; |
308 |
ev.mouse.type = sme_motionNotify; |
309 |
ev.mouse.button1 = mouseButton[0]; |
310 |
ev.mouse.button2 = mouseButton[1]; |
311 |
ev.mouse.button3 = mouseButton[2]; |
312 |
ev.mouse.dbutton = 0; |
313 |
ev.mouse.x = event.motion.y; |
314 |
ev.mouse.y = event.motion.x; |
315 |
ev.mouse.relx = event.motion.xrel; |
316 |
ev.mouse.rely = event.motion.yrel; |
317 |
gMouse->handleEvent(ev); |
318 |
return true; |
319 |
case SDL_ACTIVEEVENT: |
320 |
if (event.active.state & SDL_APPACTIVE) { |
321 |
gDisplay->setExposed(event.active.gain); |
322 |
} |
323 |
if (event.active.state & SDL_APPINPUTFOCUS) { |
324 |
if (!event.active.gain) { |
325 |
gDisplay->setMouseGrab(false); |
326 |
} |
327 |
} |
328 |
return true; |
329 |
case SDL_QUIT: |
330 |
gDisplay->setFullscreenMode(false); |
331 |
return false; |
332 |
} |
333 |
return true; |
334 |
} |
335 |
|
336 |
static Uint32 SDL_redrawCallback(Uint32 interval, void *param) |
337 |
{ |
338 |
SDL_Event event; |
339 |
|
340 |
if (!gSDLVideoExposePending) { |
341 |
event.type = SDL_VIDEOEXPOSE; |
342 |
// according to the docs, "You may always call SDL_PushEvent" in an SDL |
343 |
// timer callback function |
344 |
SDL_PushEvent(&event); |
345 |
gSDLVideoExposePending = true; |
346 |
} |
347 |
return interval; |
348 |
} |
349 |
|
350 |
sys_timer gSDLRedrawTimer; |
351 |
static bool eventThreadAlive; |
352 |
|
353 |
static void *SDLeventLoop(void *p) |
354 |
{ |
355 |
eventThreadAlive = true; |
356 |
#ifdef __WIN32__ |
357 |
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE) < 0) { |
358 |
#else |
359 |
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_EVENTTHREAD | SDL_INIT_NOPARACHUTE) < 0) { |
360 |
#endif |
361 |
ht_printf("SDL: Unable to init: %s\n", SDL_GetError()); |
362 |
exit(1); |
363 |
} |
364 |
|
365 |
atexit(SDL_Quit); // give SDl a chance to clean up before exit! |
366 |
sd = (SDLSystemDisplay*)gDisplay; |
367 |
|
368 |
sd->initCursor(); |
369 |
|
370 |
sd->updateTitle(); |
371 |
sd->mEventThreadID = SDL_ThreadID(); |
372 |
|
373 |
SDL_WM_GrabInput(SDL_GRAB_OFF); |
374 |
|
375 |
sd->changeResolution(sd->mClientChar); |
376 |
sd->setExposed(true); |
377 |
|
378 |
gSDLVideoExposePending = false; |
379 |
SDL_RedrawTimerID = SDL_AddTimer(gDisplay->mRedraw_ms, SDL_redrawCallback, NULL); |
380 |
|
381 |
sd->setFullscreenMode(sd->mFullscreen); |
382 |
|
383 |
SDL_Event event; |
384 |
do { |
385 |
SDL_WaitEvent(&event); |
386 |
} while (handleSDLEvent(event)); |
387 |
|
388 |
gDisplay->setMouseGrab(false); |
389 |
|
390 |
if (SDL_RedrawTimerID) |
391 |
SDL_RemoveTimer(SDL_RedrawTimerID); |
392 |
|
393 |
ppc_cpu_stop(); |
394 |
|
395 |
eventThreadAlive = false; |
396 |
|
397 |
return NULL; |
398 |
} |
399 |
|
400 |
SystemDisplay *allocSystemDisplay(const char *title, const DisplayCharacteristics &chr, int redraw_ms); |
401 |
SystemKeyboard *allocSystemKeyboard(); |
402 |
SystemMouse *allocSystemMouse(); |
403 |
|
404 |
void initUI(const char *title, const DisplayCharacteristics &aCharacteristics, int redraw_ms, const KeyboardCharacteristics &keyConfig, bool fullscreen) |
405 |
{ |
406 |
#if 0 |
407 |
createSDLToADBKeytable(); |
408 |
#endif |
409 |
|
410 |
sys_thread SDLeventLoopThread; |
411 |
|
412 |
gDisplay = allocSystemDisplay(title, aCharacteristics, redraw_ms); |
413 |
gMouse = allocSystemMouse(); |
414 |
gKeyboard = allocSystemKeyboard(); |
415 |
if (!gKeyboard->setKeyConfig(keyConfig)) { |
416 |
ht_printf("no keyConfig, or is empty"); |
417 |
exit(1); |
418 |
} |
419 |
|
420 |
gDisplay->mFullscreen = fullscreen; |
421 |
|
422 |
if (sys_create_thread(&SDLeventLoopThread, 0, SDLeventLoop, NULL)) { |
423 |
ht_printf("SDL: can't create event thread!\n"); |
424 |
exit(1); |
425 |
} |
426 |
} |
427 |
|
428 |
void doneUI() |
429 |
{ |
430 |
if (eventThreadAlive) { |
431 |
SDL_Event event; |
432 |
event.type = SDL_QUIT; |
433 |
SDL_PushEvent(&event); |
434 |
while (eventThreadAlive) SDL_Delay(10); // FIXME: UGLY! |
435 |
} |
436 |
SDL_Quit(); |
437 |
} |