ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/Display_EmbeddedSDL.h
Revision: 1.1
Committed: 2007-01-28T16:02:56Z (17 years, 2 months ago) by berlac
Content type: text/plain
Branch: MAIN
Log Message:
Initial revision.

File Contents

# User Rev Content
1 berlac 1.1 /*
2     * DisplayEmbeddedSDL.h - C64 graphics display, emulator window handling
3     * for embedded Linux devices (Qtopia, Maemo)
4     *
5     * Frodo (C) 1994-1997,2002-2005 Christian Bauer
6     * Changes for embedded Linux devices (Qtopia, Maemo) (C) 2006 Bernd Lachner
7     *
8     * This program is free software; you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License as published by
10     * the Free Software Foundation; either version 2 of the License, or
11     * (at your option) any later version.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21     */
22    
23     #include "C64.h"
24     #include "SAM.h"
25     #include "main.h"
26     #include "Version.h"
27    
28     #include "sdlgui.h"
29     #include "dlgMain.h"
30    
31     #define QWS
32     #include <SDL.h>
33     #include <SDL_thread.h>
34    
35     // Display surface
36     static SDL_Surface *screen = 0;
37     static SDL_Surface *backgroundSurf = 0;
38     static SDL_Surface *surf = 0;
39    
40     static SDL_mutex *screenLock = 0;
41    
42     // Mode of Joystick emulation. 0 = none, 1 = Joyport 1, 2 = Joyport 2
43     static short joy_emu = 0;
44    
45     // Keyboard
46     static bool tab_pressed = false;
47    
48     // For LED error blinking
49     static C64Display *c64_disp;
50     static struct sigaction pulse_sa;
51     static itimerval pulse_tv;
52    
53     // SDL joysticks
54     static SDL_Joystick *joy[2] = {NULL, NULL};
55    
56     // Colors for speedometer/drive LEDs
57     enum
58     {
59     black = 0,
60     white = 1,
61     fill_gray = 16,
62     shine_gray = 17,
63     shadow_gray = 18,
64     red = 19,
65     green = 20,
66     PALETTE_SIZE = 21
67     };
68    
69     /*
70     C64 keyboard matrix:
71    
72     Bit 7 6 5 4 3 2 1 0
73     0 CUD F5 F3 F1 F7 CLR RET DEL
74     1 SHL E S Z 4 A W 3
75     2 X T F C 6 D R 5
76     3 V U H B 8 G Y 7
77     4 N O K M 0 J I 9
78     5 , @ : . - L P +
79     6 / ^ = SHR HOM ; *
80     7 R/S Q C= SPC 2 CTL <- 1
81     */
82    
83     #define MATRIX(a,b) (((a) << 3) | (b))
84    
85    
86     /*
87     * Open window
88     */
89    
90     char *buffer;
91    
92     int width = 320;
93     int height = 240;
94    
95     bool isGuiAvailable = true; // TODO from main.cpp
96     bool GUIOpened = false;
97    
98     static SDL_Thread *GUIthread = NULL;
99     static const int GUI_RETURN_INFO = (SDL_USEREVENT+1);
100     static bool doUpdate = true;
101    
102     void update( int32 x, int32 y, int32 w, int32 h, bool forced )
103     {
104     if ( !forced && !doUpdate ) // the HW surface is available
105     return;
106    
107     // SDL_UpdateRect(SDL_GetVideoSurface(), 0, 0, width, height);
108     // SDL_UpdateRect(surf, x, y, w, h);
109     SDL_UpdateRect(screen, x, y, w, h);
110     }
111    
112     void update( bool forced )
113     {
114     update( 0, 0, width, height, forced );
115     }
116    
117     void update()
118     {
119     update( 0, 0, width, height, false );
120     }
121    
122     void restoreBackground()
123     {
124     if (backgroundSurf != NULL) {
125     SDL_BlitSurface(backgroundSurf, NULL, screen, NULL);
126     update(true);
127     fprintf(stderr, "video surface restored\n");
128     }
129     }
130    
131     void allocateBackgroundSurf()
132     {
133     // allocate new background video surface
134     backgroundSurf = SDL_ConvertSurface(screen, screen->format, screen->flags);
135     fprintf(stderr, "Allocating background video surface\n");
136     }
137    
138     void freeBackgroundSurf()
139     {
140     // free background video surface
141     if (backgroundSurf != NULL)
142     {
143     fprintf(stderr, "Freeing background video surface\n");
144     SDL_FreeSurface(backgroundSurf);
145     backgroundSurf = NULL;
146     }
147     }
148    
149     void openGUI()
150     {
151     fprintf(stderr, "open GUI\n");
152     if (GUIOpened)
153     {
154     fprintf(stderr, "GUI is already open!\n");
155     return;
156     }
157     allocateBackgroundSurf();
158     surf = backgroundSurf;
159     GUIOpened = true;
160     }
161    
162     void closeGUI()
163     {
164     fprintf(stderr, "close GUI\n");
165     // update the main surface and then redirect VDI to it
166     restoreBackground();
167     surf = screen; // redirect VDI to main surface
168     fprintf(stderr, "VDI redirected back to main video surface\n");
169     freeBackgroundSurf();
170     GUIOpened = false;
171     }
172    
173     void saveBackground()
174     {
175     if (backgroundSurf != NULL) {
176     SDL_BlitSurface(screen, NULL, backgroundSurf, NULL);
177     surf = backgroundSurf; // redirect VDI to background surface
178     fprintf(stderr, "video surface saved to background, VDI redirected\n");
179     }
180     }
181    
182     void blendBackgrounds()
183     {
184     if (backgroundSurf != NULL)
185     {
186     SDL_Rect *Rect;
187     Rect = SDLGui_GetFirstBackgroundRect();
188     while (Rect != NULL)
189     {
190     SDL_BlitSurface(backgroundSurf, Rect, screen, Rect);
191     Rect = SDLGui_GetNextBackgroundRect();
192     }
193     update(true);
194     }
195     }
196    
197     static Prefs DialogPrefs;
198    
199     // running in a different thread
200     static int open_gui(void * /*ptr*/)
201     {
202     openGUI();
203     DialogPrefs = ThePrefs;
204     // Show main dialog
205     int status = Dialog_Main(DialogPrefs);
206     // The status is sent to event checking thread by the USEREVENT+1 message
207     SDL_Event ev;
208     ev.type = GUI_RETURN_INFO;
209     ev.user.code = status; // STATUS_SHUTDOWN or STATUS_REBOOT
210     ev.user.data1 = NULL;
211     SDL_PeepEvents(&ev, 1, SDL_ADDEVENT, SDL_EVENTMASK(GUI_RETURN_INFO));
212     closeGUI();
213     return 0;
214     }
215    
216     bool start_GUI_thread()
217     {
218     if (isGuiAvailable) // TODO && !hostScreen.isGUIopen())
219     {
220     GUIthread = SDL_CreateThread(open_gui, NULL);
221     }
222     return (GUIthread != NULL);
223     }
224    
225     void kill_GUI_thread()
226     {
227     if (GUIthread != NULL) {
228     SDL_KillThread(GUIthread);
229     GUIthread = NULL;
230     }
231     }
232    
233     void screenlock()
234     {
235     while (SDL_mutexP(screenLock)==-1)
236     {
237     SDL_Delay(20);
238     fprintf(stderr, "Couldn't lock mutex\n");
239     }
240     }
241    
242     void screenunlock()
243     {
244     while (SDL_mutexV(screenLock)==-1)
245     {
246     SDL_Delay(20);
247     fprintf(stderr, "Couldn't unlock mutex\n");
248     }
249     }
250    
251     int init_graphics(void)
252     {
253     // Init SDL
254     if (SDL_Init(SDL_INIT_VIDEO) < 0) {
255     fprintf(stderr, "Couldn't initialize SDL (%s)\n", SDL_GetError());
256     return 0;
257     }
258    
259     screenLock = SDL_CreateMutex();
260    
261     buffer = new char[DISPLAY_X*DISPLAY_Y];
262     // Open window
263     SDL_WM_SetCaption(VERSION_STRING, "Frodo");
264     screen = SDL_SetVideoMode(320, 240, 8, SDL_DOUBLEBUF);
265     surf = screen;
266     if (screen == NULL)
267     {
268     fprintf(stderr, "SDL Couldn't set video mode to %d x %d\n", DISPLAY_X, DISPLAY_Y+17);
269     }
270     else
271     {
272     fprintf(stderr, "SDL Set video mode to %d x %d\n", DISPLAY_X, DISPLAY_Y+17);
273     SDLGui_Init(screen);
274     start_GUI_thread();
275     }
276     return 1;
277     }
278    
279    
280    
281     /*
282     * Display constructor
283     */
284    
285     C64Display::C64Display(C64 *the_c64) : TheC64(the_c64)
286     {
287     quit_requested = false;
288     speedometer_string[0] = 0;
289    
290     // LEDs off
291     for (int i=0; i<4; i++)
292     led_state[i] = old_led_state[i] = LED_OFF;
293    
294     // Start timer for LED error blinking
295     c64_disp = this;
296     pulse_sa.sa_handler = (void (*)(int))pulse_handler;
297     pulse_sa.sa_flags = SA_RESTART;
298     sigemptyset(&pulse_sa.sa_mask);
299     sigaction(SIGALRM, &pulse_sa, NULL);
300     pulse_tv.it_interval.tv_sec = 0;
301     pulse_tv.it_interval.tv_usec = 400000;
302     pulse_tv.it_value.tv_sec = 0;
303     pulse_tv.it_value.tv_usec = 400000;
304     setitimer(ITIMER_REAL, &pulse_tv, NULL);
305     }
306    
307    
308     /*
309     * Display destructor
310     */
311    
312     C64Display::~C64Display()
313     {
314     SDL_Quit();
315     delete[] buffer;
316     }
317    
318    
319     /*
320     * Prefs may have changed
321     */
322    
323     void C64Display::NewPrefs(Prefs *prefs)
324     {
325     }
326    
327    
328     /*
329     * Redraw bitmap
330     */
331    
332     void C64Display::Update(void)
333     {
334     screenlock();
335     if (surf == NULL)
336     return;
337     int iOffsetX = (DISPLAY_X - surf->w) / 2;
338     int iOffsetY = (DISPLAY_Y - surf->h) / 2;
339     for (int j=0; j < surf->h - 17; j++)
340     {
341     memcpy(static_cast<char*>(surf->pixels)+surf->w*j, buffer+iOffsetX+DISPLAY_X*(j+iOffsetY), surf->w);
342     }
343     // Draw speedometer/LEDs
344     SDL_Rect r = {0, (surf->h - 17), DISPLAY_X, 15};
345     SDL_FillRect(surf, &r, fill_gray);
346     r.w = DISPLAY_X; r.h = 1;
347     SDL_FillRect(surf, &r, shine_gray);
348     r.y = (surf->h - 17) + 14;
349     SDL_FillRect(surf, &r, shadow_gray);
350     r.w = 16;
351     for (int i=2; i<5; i++)
352     {
353     r.x = DISPLAY_X * i/5 - 24; r.y = (surf->h - 17) + 4;
354     SDL_FillRect(surf, &r, shadow_gray);
355     r.y = (surf->h - 17) + 10;
356     SDL_FillRect(surf, &r, shine_gray);
357     }
358     r.y = (surf->h - 17); r.w = 1; r.h = 15;
359     for (int i=0; i<4; i++)
360     {
361     r.x = DISPLAY_X * i / 5;
362     SDL_FillRect(surf, &r, shine_gray);
363     r.x = DISPLAY_X * (i+1) / 5 - 1;
364     SDL_FillRect(surf, &r, shadow_gray);
365     }
366     r.y = (surf->h - 17) + 4; r.h = 7;
367     for (int i=2; i<5; i++)
368     {
369     r.x = DISPLAY_X * i/5 - 24;
370     SDL_FillRect(surf, &r, shadow_gray);
371     r.x = DISPLAY_X * i/5 - 9;
372     SDL_FillRect(surf, &r, shine_gray);
373     }
374     r.y = (surf->h - 17) + 5; r.w = 14; r.h = 5;
375     for (int i=0; i<3; i++)
376     {
377     r.x = DISPLAY_X * (i+2) / 5 - 23;
378     int c;
379     switch (led_state[i])
380     {
381     case LED_ON:
382     c = green;
383     break;
384     case LED_ERROR_ON:
385     c = red;
386     break;
387     default:
388     c = black;
389     break;
390     }
391     SDL_FillRect(surf, &r, c);
392     }
393    
394     draw_string(surf, DISPLAY_X * 1/5 + 8, (surf->h - 17) + 4, "D\x12 8", black, fill_gray);
395     draw_string(surf, DISPLAY_X * 2/5 + 8, (surf->h - 17) + 4, "D\x12 9", black, fill_gray);
396     draw_string(surf, DISPLAY_X * 3/5 + 8, (surf->h - 17) + 4, "D\x12 10", black, fill_gray);
397     if (joy_emu == 1)
398     draw_string(surf, DISPLAY_X * 4/5 + 2, (surf->h - 17) + 4, "1", black, fill_gray);
399     else if (joy_emu == 2)
400     draw_string(surf, DISPLAY_X * 4/5 + 2, (surf->h - 17) + 4, "2", black, fill_gray);
401     draw_string(surf, 24, (surf->h - 17) + 4, speedometer_string, black, fill_gray);
402    
403     // Update display
404     SDL_Flip(surf);
405    
406     blendBackgrounds();
407     screenunlock();
408     }
409    
410    
411     /*
412     * Draw string into surface using the C64 ROM font
413     */
414    
415     void C64Display::draw_string(SDL_Surface *s, int x, int y, const char *str, uint8 front_color, uint8 back_color)
416     {
417     uint8 *pb = (uint8 *)s->pixels + s->pitch*y + x;
418     char c;
419     while ((c = *str++) != 0)
420     {
421     uint8 *q = TheC64->Char + c*8 + 0x800;
422     uint8 *p = pb;
423     for (int y=0; y<8; y++)
424     {
425     uint8 v = *q++;
426     p[0] = (v & 0x80) ? front_color : back_color;
427     p[1] = (v & 0x40) ? front_color : back_color;
428     p[2] = (v & 0x20) ? front_color : back_color;
429     p[3] = (v & 0x10) ? front_color : back_color;
430     p[4] = (v & 0x08) ? front_color : back_color;
431     p[5] = (v & 0x04) ? front_color : back_color;
432     p[6] = (v & 0x02) ? front_color : back_color;
433     p[7] = (v & 0x01) ? front_color : back_color;
434     p += s->pitch;
435     }
436     pb += 8;
437     }
438     }
439    
440    
441     /*
442     * LED error blink
443     */
444    
445     void C64Display::pulse_handler(...)
446     {
447     for (int i=0; i<4; i++)
448     switch (c64_disp->led_state[i])
449     {
450     case LED_ERROR_ON:
451     c64_disp->led_state[i] = LED_ERROR_OFF;
452     break;
453     case LED_ERROR_OFF:
454     c64_disp->led_state[i] = LED_ERROR_ON;
455     break;
456     }
457     }
458    
459    
460     /*
461     * Draw speedometer
462     */
463    
464     void C64Display::Speedometer(int speed)
465     {
466     static int delay = 0;
467    
468     if (delay >= 20)
469     {
470     delay = 0;
471     sprintf(speedometer_string, "%d%%", speed);
472     }
473     else
474     delay++;
475     }
476    
477    
478     /*
479     * Return pointer to bitmap data
480     */
481    
482     uint8 *C64Display::BitmapBase(void)
483     {
484     //return (uint8 *)screen->pixels;
485     return (uint8 *)buffer;
486     }
487    
488    
489     /*
490     * Return number of bytes per row
491     */
492    
493     int C64Display::BitmapXMod(void)
494     {
495     //return screen->pitch;
496     return DISPLAY_X;
497     }
498    
499    
500    
501     /*
502     * Poll the keyboard
503     */
504    
505     static void translate_key(SDLKey key, bool key_up, uint8 *key_matrix, uint8 *rev_matrix, uint8 *joystick)
506     {
507     int c64_key = -1;
508     if (tab_pressed)
509     {
510     // Function and run/stop key emulation on Zaurus keyboard
511     switch (key)
512     {
513     case SDLK_q: c64_key = MATRIX(0,4); break;
514     case SDLK_w: c64_key = MATRIX(0,4) | 0x80; break;
515     case SDLK_e: c64_key = MATRIX(0,5); break;
516     case SDLK_r: c64_key = MATRIX(0,5) | 0x80; break;
517     case SDLK_t: c64_key = MATRIX(0,6); break;
518     case SDLK_z: c64_key = MATRIX(0,6) | 0x80; break;
519     case SDLK_u: c64_key = MATRIX(0,3); break;
520     case SDLK_i: c64_key = MATRIX(0,3) | 0x80; break;
521     case SDLK_o: c64_key = MATRIX(7,7); break;
522     }
523     }
524     else
525     {
526     switch (key)
527     {
528     case SDLK_a: c64_key = MATRIX(1,2); break;
529     case SDLK_b: c64_key = MATRIX(3,4); break;
530     case SDLK_c: c64_key = MATRIX(2,4); break;
531     case SDLK_d: c64_key = MATRIX(2,2); break;
532     case SDLK_e: c64_key = MATRIX(1,6); break;
533     case SDLK_f: c64_key = MATRIX(2,5); break;
534     case SDLK_g: c64_key = MATRIX(3,2); break;
535     case SDLK_h: c64_key = MATRIX(3,5); break;
536     case SDLK_i: c64_key = MATRIX(4,1); break;
537     case SDLK_j: c64_key = MATRIX(4,2); break;
538     case SDLK_k: c64_key = MATRIX(4,5); break;
539     case SDLK_l: c64_key = MATRIX(5,2); break;
540     case SDLK_m: c64_key = MATRIX(4,4); break;
541     case SDLK_n: c64_key = MATRIX(4,7); break;
542     case SDLK_o: c64_key = MATRIX(4,6); break;
543     case SDLK_p: c64_key = MATRIX(5,1); break;
544     case SDLK_q: c64_key = MATRIX(7,6); break;
545     case SDLK_r: c64_key = MATRIX(2,1); break;
546     case SDLK_s: c64_key = MATRIX(1,5); break;
547     case SDLK_t: c64_key = MATRIX(2,6); break;
548     case SDLK_u: c64_key = MATRIX(3,6); break;
549     case SDLK_v: c64_key = MATRIX(3,7); break;
550     case SDLK_w: c64_key = MATRIX(1,1); break;
551     case SDLK_x: c64_key = MATRIX(2,7); break;
552     case SDLK_y: c64_key = MATRIX(3,1); break;
553     case SDLK_z: c64_key = MATRIX(1,4); break;
554    
555     case SDLK_0: c64_key = MATRIX(4,3); break;
556     case SDLK_1: c64_key = MATRIX(7,0); break;
557     case SDLK_2: c64_key = MATRIX(7,3); break;
558     case SDLK_3: c64_key = MATRIX(1,0); break;
559     case SDLK_4: c64_key = MATRIX(1,3); break;
560     case SDLK_5: c64_key = MATRIX(2,0); break;
561     case SDLK_6: c64_key = MATRIX(2,3); break;
562     case SDLK_7: c64_key = MATRIX(3,0); break;
563     case SDLK_8: c64_key = MATRIX(3,3); break;
564     case SDLK_9: c64_key = MATRIX(4,0); break;
565    
566     case SDLK_SPACE: c64_key = MATRIX(7,4); break;
567     case SDLK_BACKQUOTE: c64_key = MATRIX(7,1); break;
568     case SDLK_BACKSLASH: c64_key = MATRIX(6,6); break;
569     case SDLK_COMMA: c64_key = MATRIX(5,7); break;
570     case SDLK_PERIOD: c64_key = MATRIX(5,4); break;
571     case SDLK_MINUS: c64_key = MATRIX(5,0); break;
572     case SDLK_EQUALS: c64_key = MATRIX(5,3); break;
573     case SDLK_LEFTBRACKET: c64_key = MATRIX(5,6); break;
574     case SDLK_RIGHTBRACKET: c64_key = MATRIX(6,1); break;
575     case SDLK_SEMICOLON: c64_key = MATRIX(5,5); break;
576     case SDLK_QUOTE: c64_key = MATRIX(6,2); break;
577     case SDLK_SLASH: c64_key = MATRIX(6,7); break;
578    
579     case SDLK_ESCAPE: c64_key = MATRIX(7,7); break;
580     case SDLK_RETURN: c64_key = MATRIX(0,1); break;
581     case SDLK_BACKSPACE: case SDLK_DELETE: c64_key = MATRIX(0,0); break;
582     case SDLK_INSERT: c64_key = MATRIX(6,3); break;
583     case SDLK_HOME: c64_key = MATRIX(6,3); break;
584     case SDLK_END: c64_key = MATRIX(6,0); break;
585     case SDLK_PAGEUP: c64_key = MATRIX(6,0); break;
586     case SDLK_PAGEDOWN: c64_key = MATRIX(6,5); break;
587    
588     case SDLK_LCTRL: c64_key = MATRIX(7,2); break;
589     case SDLK_RCTRL: c64_key = MATRIX(7,5); break;
590     case SDLK_LSHIFT: c64_key = MATRIX(1,7); break;
591     case SDLK_RSHIFT: c64_key = MATRIX(6,4); break;
592     case SDLK_LALT: case SDLK_LMETA: c64_key = MATRIX(7,5); break;
593     case SDLK_RALT: case SDLK_RMETA: c64_key = MATRIX(7,5); break;
594    
595     case SDLK_UP: c64_key = MATRIX(0,7)| 0x80; break;
596     case SDLK_DOWN: c64_key = MATRIX(0,7); break;
597     case SDLK_LEFT: c64_key = MATRIX(0,2) | 0x80; break;
598     case SDLK_RIGHT: c64_key = MATRIX(0,2); break;
599    
600     case SDLK_F1: c64_key = MATRIX(0,4); break;
601     case SDLK_F2: c64_key = MATRIX(0,4) | 0x80; break;
602     case SDLK_F3: c64_key = MATRIX(0,5); break;
603     case SDLK_F4: c64_key = MATRIX(0,5) | 0x80; break;
604     case SDLK_F5: c64_key = MATRIX(0,6); break;
605     case SDLK_F6: c64_key = MATRIX(0,6) | 0x80; break;
606     case SDLK_F7: c64_key = MATRIX(0,3); break;
607     case SDLK_F8: c64_key = MATRIX(0,3) | 0x80; break;
608    
609     case SDLK_KP0: case SDLK_KP5: c64_key = 0x10 | 0x40; break;
610     case SDLK_KP1: c64_key = 0x06 | 0x40; break;
611     case SDLK_KP2: c64_key = 0x02 | 0x40; break;
612     case SDLK_KP3: c64_key = 0x0a | 0x40; break;
613     case SDLK_KP4: c64_key = 0x04 | 0x40; break;
614     case SDLK_KP6: c64_key = 0x08 | 0x40; break;
615     case SDLK_KP7: c64_key = 0x05 | 0x40; break;
616     case SDLK_KP8: c64_key = 0x01 | 0x40; break;
617     case SDLK_KP9: c64_key = 0x09 | 0x40; break;
618    
619     case SDLK_KP_DIVIDE: c64_key = MATRIX(6,7); break;
620     case SDLK_KP_ENTER: c64_key = MATRIX(0,1); break;
621    
622     // Support for Zaurus/Qtopia
623     case SDLK_QUOTEDBL: c64_key = MATRIX(7,3) | 0x80; break;
624     case SDLK_ASTERISK: c64_key = MATRIX(6,1); break;
625     case SDLK_DOLLAR: c64_key = MATRIX(1,3) | 0x80; break;
626     case SDLK_COLON: c64_key = MATRIX(5,5); break;
627     case SDLK_AT: c64_key = MATRIX(5,6); break;
628     }
629     }
630     if (c64_key < 0)
631     return;
632    
633     // Zaurus/Qtopia joystick emulation
634     if (joy_emu != 0)
635     {
636     switch (key)
637     {
638     case SDLK_SPACE: c64_key = 0x10 | 0x40; break;
639     case SDLK_UP: c64_key = 0x01 | 0x40; break;
640     case SDLK_DOWN: c64_key = 0x02 | 0x40; break;
641     case SDLK_LEFT: c64_key = 0x04 | 0x40; break;
642     case SDLK_RIGHT: c64_key = 0x08 | 0x40; break;
643     }
644     }
645    
646     // Handle joystick emulation
647     if (c64_key & 0x40)
648     {
649     c64_key &= 0x1f;
650     if (key_up)
651     *joystick |= c64_key;
652     else
653     *joystick &= ~c64_key;
654     return;
655     }
656    
657     // Handle other keys
658     bool shifted = c64_key & 0x80;
659     int c64_byte = (c64_key >> 3) & 7;
660     int c64_bit = c64_key & 7;
661     if (key_up)
662     {
663     if (shifted)
664     {
665     key_matrix[6] |= 0x10;
666     rev_matrix[4] |= 0x40;
667     }
668     key_matrix[c64_byte] |= (1 << c64_bit);
669     rev_matrix[c64_bit] |= (1 << c64_byte);
670     }
671     else
672     {
673     if (shifted)
674     {
675     key_matrix[6] &= 0xef;
676     rev_matrix[4] &= 0xbf;
677     }
678     key_matrix[c64_byte] &= ~(1 << c64_bit);
679     rev_matrix[c64_bit] &= ~(1 << c64_byte);
680     }
681     }
682    
683     void C64Display::PollKeyboard(uint8 *key_matrix, uint8 *rev_matrix, uint8 *joystick)
684     {
685     SDL_Event event;
686     int eventmask = SDL_EVENTMASK(SDL_KEYDOWN)
687     | SDL_EVENTMASK(SDL_KEYUP)
688     | SDL_EVENTMASK(SDL_MOUSEBUTTONDOWN)
689     | SDL_EVENTMASK(SDL_MOUSEBUTTONUP)
690     | SDL_EVENTMASK(SDL_MOUSEMOTION)
691     | SDL_EVENTMASK(SDL_JOYAXISMOTION)
692     | SDL_EVENTMASK(SDL_JOYHATMOTION)
693     | SDL_EVENTMASK(SDL_JOYBUTTONDOWN)
694     | SDL_EVENTMASK(SDL_JOYBUTTONUP)
695     | SDL_EVENTMASK(SDL_ACTIVEEVENT)
696     | SDL_EVENTMASK(GUI_RETURN_INFO)
697     | SDL_EVENTMASK(SDL_QUIT);
698    
699     SDL_PumpEvents();
700     while (SDL_PeepEvents(&event, 1, SDL_GETEVENT, eventmask))
701     {
702     if (GUIOpened)
703     {
704     if (event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP)
705     {
706     if (event.type == SDL_MOUSEBUTTONDOWN)
707     fprintf(stderr, "Mouse down\n");
708     if (event.type == SDL_MOUSEBUTTONUP)
709     fprintf(stderr, "Mouse up\n");
710     SDL_Event ev;
711     ev.type = SDL_USEREVENT; // map button down/up to user event
712     ev.user.code = event.type;
713     ev.user.data1 = (void *)(int)event.button.x;
714     ev.user.data2 = (void *)(int)event.button.y;
715     SDL_PeepEvents(&ev, 1, SDL_ADDEVENT, SDL_EVENTMASK(SDL_USEREVENT));
716     }
717     else if (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP)
718     {
719     if (event.type == SDL_KEYDOWN)
720     fprintf(stderr, "Key down\n");
721     if (event.type == SDL_KEYUP)
722     fprintf(stderr, "Key up\n");
723     SDLKey sym = event.key.keysym.sym;
724     int state = SDL_GetModState(); // keysym.mod does not deliver single mod key presses for
725     SDL_Event ev;
726     ev.type = SDL_USEREVENT; // map key down/up event to user event
727     ev.user.code = event.type;
728     ev.user.data1 = (void *)(int)sym;
729     ev.user.data2 = (void *)(int)state;
730     SDL_PeepEvents(&ev, 1, SDL_ADDEVENT, SDL_EVENTMASK(SDL_USEREVENT));
731     }
732     }
733     else
734     {
735     switch (event.type)
736     {
737     case GUI_RETURN_INFO:
738     {
739     fprintf(stderr, "Return code from gui: %d\n", event.user.code);
740     switch (event.user.code)
741     {
742     case DO_RESET:
743     TheC64->Reset();
744     break;
745     case DO_QUIT:
746     quit_requested = true;
747     break;
748     case DO_USEPREFS:
749     TheC64->NewPrefs(&DialogPrefs);
750     ThePrefs = DialogPrefs;
751     break;
752     case DO_SAVEPREFS:
753     TheC64->NewPrefs(&DialogPrefs);
754     ThePrefs = DialogPrefs;
755     ThePrefs.Save(Frodo::get_prefs_path());
756     break;
757     }
758     break;
759     }
760     case SDL_MOUSEBUTTONDOWN:
761     case SDL_MOUSEBUTTONUP:
762     start_GUI_thread();
763     break;
764     // Key pressed
765     case SDL_KEYDOWN:
766     // fprintf(stderr, "SDL-Key: %d\n", event.key.keysym.sym);
767     if (tab_pressed && event.key.keysym.sym == SDLK_j)
768     {
769     if (joy_emu < 2)
770     joy_emu++;
771     else
772     joy_emu = 0;
773     }
774     if (tab_pressed && event.key.keysym.sym == SDLK_p)
775     {
776     // NMI (Restore)
777     TheC64->NMI();
778     }
779     else
780     {
781     switch (event.key.keysym.sym)
782     {
783     case SDLK_TAB:
784     tab_pressed = true;
785     break;
786    
787     case SDLK_F9: // F9: Invoke SAM
788     SAM(TheC64);
789     break;
790    
791     case SDLK_F11: // F10: Quit
792     // Iconify not implemented in Qtopia SDL yet. Quit instead show gui.
793     //SDL_WM_IconifyWindow();
794     quit_requested = true;
795     break;
796    
797     case SDLK_F12: // F12: Reset
798     TheC64->Reset();
799     break;
800    
801     case SDLK_KP_PLUS: // '+' on keypad: Increase SkipFrames
802     ThePrefs.SkipFrames++;
803     break;
804    
805     case SDLK_KP_MINUS: // '-' on keypad: Decrease SkipFrames
806     if (ThePrefs.SkipFrames > 1)
807     ThePrefs.SkipFrames--;
808     break;
809    
810     case SDLK_KP_MULTIPLY: // '*' on keypad: Toggle speed limiter
811     ThePrefs.LimitSpeed = !ThePrefs.LimitSpeed;
812     break;
813    
814     default:
815     translate_key(event.key.keysym.sym, false, key_matrix, rev_matrix, joystick);
816     break;
817     }
818     }
819     break;
820    
821     // Key released
822     case SDL_KEYUP:
823     if (event.key.keysym.sym == SDLK_TAB)
824     tab_pressed = false;
825     else
826     {
827     translate_key(event.key.keysym.sym, true, key_matrix, rev_matrix, joystick);
828     }
829     break;
830    
831     // Quit Frodo
832     case SDL_QUIT:
833     quit_requested = true;
834     break;
835     }
836     }
837     }
838     }
839    
840    
841     /*
842     * Check if NumLock is down (for switching the joystick keyboard emulation)
843     */
844    
845     bool C64Display::NumLock(void)
846     {
847     if (joy_emu == 2)
848     return true;
849     return false;
850     }
851    
852    
853     /*
854     * Open/close joystick drivers given old and new state of
855     * joystick preferences
856     */
857    
858     void C64::open_close_joystick(int port, int oldjoy, int newjoy)
859     {
860     if (oldjoy != newjoy) {
861     joy_minx[port] = joy_miny[port] = 32767; // Reset calibration
862     joy_maxx[port] = joy_maxy[port] = -32768;
863     if (newjoy) {
864     joy[port] = SDL_JoystickOpen(newjoy - 1);
865     if (joy[port] == NULL)
866     fprintf(stderr, "Couldn't open joystick %d\n", port + 1);
867     } else {
868     if (joy[port]) {
869     SDL_JoystickClose(joy[port]);
870     joy[port] = NULL;
871     }
872     }
873     }
874     }
875    
876     void C64::open_close_joysticks(int oldjoy1, int oldjoy2, int newjoy1, int newjoy2)
877     {
878     open_close_joystick(0, oldjoy1, newjoy1);
879     open_close_joystick(1, oldjoy2, newjoy2);
880     }
881    
882    
883     /*
884     * Poll joystick port, return CIA mask
885     */
886    
887     uint8 C64::poll_joystick(int port)
888     {
889     uint8 j = 0xff;
890    
891     if (port == 0 && (joy[0] || joy[1]))
892     SDL_JoystickUpdate();
893    
894     if (joy[port]) {
895     int x = SDL_JoystickGetAxis(joy[port], 0), y = SDL_JoystickGetAxis(joy[port], 1);
896    
897     if (x > joy_maxx[port])
898     joy_maxx[port] = x;
899     if (x < joy_minx[port])
900     joy_minx[port] = x;
901     if (y > joy_maxy[port])
902     joy_maxy[port] = y;
903     if (y < joy_miny[port])
904     joy_miny[port] = y;
905    
906     if (joy_maxx[port] - joy_minx[port] < 100 || joy_maxy[port] - joy_miny[port] < 100)
907     return 0xff;
908    
909     if (x < (joy_minx[port] + (joy_maxx[port]-joy_minx[port])/3))
910     j &= 0xfb; // Left
911     else if (x > (joy_minx[port] + 2*(joy_maxx[port]-joy_minx[port])/3))
912     j &= 0xf7; // Right
913    
914     if (y < (joy_miny[port] + (joy_maxy[port]-joy_miny[port])/3))
915     j &= 0xfe; // Up
916     else if (y > (joy_miny[port] + 2*(joy_maxy[port]-joy_miny[port])/3))
917     j &= 0xfd; // Down
918    
919     if (SDL_JoystickGetButton(joy[port], 0))
920     j &= 0xef; // Button
921     }
922    
923     return j;
924     }
925    
926     /*
927     * Allocate C64 colors
928     */
929    
930     void C64Display::InitColors(uint8 *colors)
931     {
932     SDL_Color palette[PALETTE_SIZE];
933     for (int i=0; i<16; i++)
934     {
935     palette[i].r = palette_red[i];
936     palette[i].g = palette_green[i];
937     palette[i].b = palette_blue[i];
938     }
939     palette[fill_gray].r = palette[fill_gray].g = palette[fill_gray].b = 0xd0;
940     palette[shine_gray].r = palette[shine_gray].g = palette[shine_gray].b = 0xf0;
941     palette[shadow_gray].r = palette[shadow_gray].g = palette[shadow_gray].b = 0x80;
942     palette[red].r = 0xf0;
943     palette[red].g = palette[red].b = 0;
944     palette[green].g = 0xf0;
945     palette[green].r = palette[green].b = 0;
946     SDL_SetColors(screen, palette, 0, PALETTE_SIZE);
947    
948     for (int i=0; i<256; i++)
949     colors[i] = i & 0x0f;
950     }
951    
952    
953     /*
954     * Show a requester (error message)
955     */
956    
957     long int ShowRequester(char *a,char *b,char *)
958     {
959     printf("%s: %s\n", a, b);
960     return 1;
961     }