/[pearpc]/src/system/ui/sdl/syssdl.cc
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /src/system/ui/sdl/syssdl.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations)
Wed Sep 5 17:11:21 2007 UTC (16 years, 7 months ago) by dpavlin
File size: 13214 byte(s)
import upstream CVS
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 }

  ViewVC Help
Powered by ViewVC 1.1.26