ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/Display_x.h
Revision: 1.3
Committed: 2003-07-14T13:59:02Z (20 years, 8 months ago) by cebix
Content type: text/plain
Branch: MAIN
Changes since 1.2: +1 -1 lines
Log Message:
specify SA_RESTART for pulse_handler; this makes SAM work correctly

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * Display_x.h - C64 graphics display, emulator window handling,
3     * X specific stuff
4     *
5 cebix 1.2 * Frodo (C) 1994-1997,2002-2003 Christian Bauer
6 cebix 1.1 *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20     */
21    
22     #include "SAM.h"
23     #include "C64.h"
24    
25     #include <X11/Xlib.h>
26     #include <X11/Xutil.h>
27     #include <X11/keysym.h>
28     #include <X11/cursorfont.h>
29    
30     #if defined(X_USE_SHM)
31     #include <sys/ipc.h>
32     #include <sys/shm.h>
33     #include <X11/extensions/XShm.h>
34     static XShmSegmentInfo shminfo;
35     #endif
36    
37     static Display *display;
38     static int screen;
39     static Window rootwin, mywin;
40    
41     static GC black_gc, led_gc;
42     static XColor black, fill_gray, shine_gray, shadow_gray, red, green;
43     static Colormap cmap;
44     static Font led_font;
45    
46     static XImage *img;
47     static Visual *vis;
48     static XVisualInfo visualInfo;
49     static int bitdepth;
50     static char *bufmem;
51     static int hsize;
52    
53     // For LED error blinking
54     static C64Display *c64_disp;
55     static struct sigaction pulse_sa;
56     static itimerval pulse_tv;
57    
58     // Keyboard and joystick
59     static int keystate[256];
60     static int joystate = 0xFF;
61     static bool num_locked = false;
62    
63     static const long int eventmask = (KeyPressMask|KeyReleaseMask|FocusChangeMask|ExposureMask);
64    
65    
66     /*
67     C64 keyboard matrix:
68    
69     Bit 7 6 5 4 3 2 1 0
70     0 CUD F5 F3 F1 F7 CLR RET DEL
71     1 SHL E S Z 4 A W 3
72     2 X T F C 6 D R 5
73     3 V U H B 8 G Y 7
74     4 N O K M 0 J I 9
75     5 , @ : . - L P +
76     6 / ^ = SHR HOM ; * £
77     7 R/S Q C= SPC 2 CTL <- 1
78     */
79    
80     #define MATRIX(a,b) (((a) << 3) | (b))
81    
82     #define KEY_F9 512
83     #define KEY_F10 513
84     #define KEY_F11 514
85     #define KEY_F12 515
86    
87     #ifdef SUN
88     #define KEY_FIRE 58
89     #define KEY_JU 135
90     #define KEY_JD 7
91     #define KEY_JL 130
92     #define KEY_JR 2
93     #else
94     #define KEY_FIRE 516
95     #define KEY_JU 517
96     #define KEY_JD 518
97     #define KEY_JL 519
98     #define KEY_JR 520
99     #endif
100    
101     #define KEY_JUL 521
102     #define KEY_JUR 522
103     #define KEY_JDL 523
104     #define KEY_JDR 524
105    
106     #define KEY_KP_PLUS 525
107     #define KEY_KP_MINUS 526
108     #define KEY_KP_MULT 527
109     #define KEY_NUM_LOCK 528
110    
111    
112     /*
113     * Decode KeySyms. This function knows about all keys that
114     * are common between different keyboard languages.
115     */
116    
117     static int kc_decode(KeySym ks)
118     {
119     switch (ks) {
120     case XK_A: case XK_a: return MATRIX(1,2);
121     case XK_B: case XK_b: return MATRIX(3,4);
122     case XK_C: case XK_c: return MATRIX(2,4);
123     case XK_D: case XK_d: return MATRIX(2,2);
124     case XK_E: case XK_e: return MATRIX(1,6);
125     case XK_F: case XK_f: return MATRIX(2,5);
126     case XK_G: case XK_g: return MATRIX(3,2);
127     case XK_H: case XK_h: return MATRIX(3,5);
128     case XK_I: case XK_i: return MATRIX(4,1);
129     case XK_J: case XK_j: return MATRIX(4,2);
130     case XK_K: case XK_k: return MATRIX(4,5);
131     case XK_L: case XK_l: return MATRIX(5,2);
132     case XK_M: case XK_m: return MATRIX(4,4);
133     case XK_N: case XK_n: return MATRIX(4,7);
134     case XK_O: case XK_o: return MATRIX(4,6);
135     case XK_P: case XK_p: return MATRIX(5,1);
136     case XK_Q: case XK_q: return MATRIX(7,6);
137     case XK_R: case XK_r: return MATRIX(2,1);
138     case XK_S: case XK_s: return MATRIX(1,5);
139     case XK_T: case XK_t: return MATRIX(2,6);
140     case XK_U: case XK_u: return MATRIX(3,6);
141     case XK_V: case XK_v: return MATRIX(3,7);
142     case XK_W: case XK_w: return MATRIX(1,1);
143     case XK_X: case XK_x: return MATRIX(2,7);
144     case XK_Y: case XK_y: return MATRIX(3,1);
145     case XK_Z: case XK_z: return MATRIX(1,4);
146    
147     case XK_0: return MATRIX(4,3);
148     case XK_1: return MATRIX(7,0);
149     case XK_2: return MATRIX(7,3);
150     case XK_3: return MATRIX(1,0);
151     case XK_4: return MATRIX(1,3);
152     case XK_5: return MATRIX(2,0);
153     case XK_6: return MATRIX(2,3);
154     case XK_7: return MATRIX(3,0);
155     case XK_8: return MATRIX(3,3);
156     case XK_9: return MATRIX(4,0);
157    
158     case XK_space: return MATRIX(7,4);
159     case XK_grave: return MATRIX(7,1);
160     case XK_backslash: return MATRIX(6,6);
161     case XK_comma: return MATRIX(5,7);
162     case XK_period: return MATRIX(5,4);
163    
164     case XK_Escape: return MATRIX(7,7);
165     case XK_Return: return MATRIX(0,1);
166     case XK_BackSpace: case XK_Delete: return MATRIX(0,0);
167     case XK_Insert: return MATRIX(6,3);
168     case XK_Home: case XK_Help: return MATRIX(6,3);
169     case XK_End: return MATRIX(6,0);
170     #ifdef __hpux
171     case XK_Prior: return MATRIX(6,0);
172     case XK_Next: return MATRIX(6,5);
173     #else
174     case XK_Page_Up: return MATRIX(6,0);
175     case XK_Page_Down: return MATRIX(6,5);
176     #endif
177     case XK_Control_L: return MATRIX(7,2);
178     case XK_Control_R: return MATRIX(7,5);
179     case XK_Shift_L: return MATRIX(1,7);
180     case XK_Shift_R: return MATRIX(6,4);
181     case XK_Alt_L: return MATRIX(7,5);
182     case XK_Alt_R: return MATRIX(7,5);
183    
184     case XK_Up: return MATRIX(0,7)| 0x80;
185     case XK_Down: return MATRIX(0,7);
186     case XK_Left: return MATRIX(0,2) | 0x80;
187     case XK_Right: return MATRIX(0,2);
188    
189     case XK_F1: return MATRIX(0,4);
190     case XK_F2: return MATRIX(0,4) | 0x80;
191     case XK_F3: return MATRIX(0,5);
192     case XK_F4: return MATRIX(0,5) | 0x80;
193     case XK_F5: return MATRIX(0,6);
194     case XK_F6: return MATRIX(0,6) | 0x80;
195     case XK_F7: return MATRIX(0,3);
196     case XK_F8: return MATRIX(0,3) | 0x80;
197    
198     case XK_F9: return KEY_F9;
199     case XK_F10: return KEY_F10;
200     case XK_F11: return KEY_F11;
201     case XK_F12: return KEY_F12;
202    
203     /* You never know which Keysyms might be missing on some workstation
204     * This #ifdef should be enough. */
205     #if defined(XK_KP_Prior) && defined(XK_KP_Left) && defined(XK_KP_Insert) && defined (XK_KP_End)
206     case XK_KP_0: case XK_KP_Insert: return KEY_FIRE;
207     case XK_KP_1: case XK_KP_End: return KEY_JDL;
208     case XK_KP_2: case XK_KP_Down: return KEY_JD;
209     case XK_KP_3: case XK_KP_Next: return KEY_JDR;
210     case XK_KP_4: case XK_KP_Left: return KEY_JL;
211     case XK_KP_5: case XK_KP_Begin: return KEY_FIRE;
212     case XK_KP_6: case XK_KP_Right: return KEY_JR;
213     case XK_KP_7: case XK_KP_Home: return KEY_JUL;
214     case XK_KP_8: case XK_KP_Up: return KEY_JU;
215     case XK_KP_9: case XK_KP_Prior: return KEY_JUR;
216     #else
217     case XK_KP_0: return KEY_FIRE;
218     case XK_KP_1: return KEY_JDL;
219     case XK_KP_2: return KEY_JD;
220     case XK_KP_3: return KEY_JDR;
221     case XK_KP_4: return KEY_JL;
222     case XK_KP_5: return KEY_FIRE;
223     case XK_KP_6: return KEY_JR;
224     case XK_KP_7: return KEY_JUL;
225     case XK_KP_8: return KEY_JU;
226     case XK_KP_9: return KEY_JUR;
227     #endif
228    
229     case XK_KP_Add: return KEY_KP_PLUS;
230     case XK_KP_Subtract: return KEY_KP_MINUS;
231     case XK_KP_Multiply: return KEY_KP_MULT;
232     case XK_KP_Divide: return MATRIX(6,7);
233     case XK_KP_Enter: return MATRIX(0,1);
234    
235     #ifdef SUN
236     case XK_Num_Lock: return KEY_NUM_LOCK;
237     #endif
238     }
239     return -1;
240     }
241    
242     static int decode_us(KeySym ks)
243     {
244     switch(ks) { /* US specific */
245     case XK_minus: return MATRIX(5,0);
246     case XK_equal: return MATRIX(5,3);
247     case XK_bracketleft: return MATRIX(5,6);
248     case XK_bracketright: return MATRIX(6,1);
249     case XK_semicolon: return MATRIX(5,5);
250     case XK_apostrophe: return MATRIX(6,2);
251     case XK_slash: return MATRIX(6,7);
252     }
253    
254     return -1;
255     }
256    
257     static int decode_de(KeySym ks)
258     {
259     switch(ks) { /* DE specific */
260     case XK_ssharp: return MATRIX(5,0);
261     case XK_apostrophe: return MATRIX(5,3);
262     case XK_Udiaeresis: case XK_udiaeresis: return MATRIX(5,6);
263     case XK_plus: return MATRIX(6,1);
264     case XK_Odiaeresis: case XK_odiaeresis: return MATRIX(5,5);
265     case XK_Adiaeresis: case XK_adiaeresis: return MATRIX(6,2);
266     case XK_numbersign: return MATRIX(6,5);
267     case XK_less: case XK_greater: return MATRIX(6,0);
268     case XK_minus: return MATRIX(6,7);
269     }
270    
271     return -1;
272     }
273    
274     static int keycode2c64(XKeyEvent *event)
275     {
276     KeySym ks;
277     int as;
278     int index = 0;
279    
280     do {
281     ks = XLookupKeysym(event, index);
282     as = kc_decode(ks);
283    
284     if (as == -1)
285     as = KBD_LANG == 0 ? decode_us(ks) : decode_de(ks);
286     if (as != -1)
287     return as;
288     index++;
289     } while (ks != NoSymbol);
290    
291     return -1;
292     }
293    
294    
295     /*
296     * Display constructor: Draw Speedometer/LEDs in window
297     */
298    
299     C64Display::C64Display(C64 *the_c64) : TheC64(the_c64)
300     {
301     int i;
302     char str[16];
303    
304     quit_requested = false;
305    
306     // LEDs off
307     for (i=0; i<4; i++)
308     led_state[i] = old_led_state[i] = LED_OFF;
309    
310     // Draw speedometer/LEDs
311     led_gc = XCreateGC(display, mywin, 0, 0);
312     XSetFont(display, led_gc, led_font);
313    
314     XSetForeground(display, led_gc, fill_gray.pixel);
315     XFillRectangle(display, mywin, led_gc, 0, DISPLAY_Y, DISPLAY_X-1, 16);
316    
317     XSetForeground(display, led_gc, shine_gray.pixel);
318     XDrawLine(display, mywin, led_gc, 0, DISPLAY_Y, DISPLAY_X-1, DISPLAY_Y);
319     for (i=0; i<5; i++)
320     XDrawLine(display, mywin, led_gc, DISPLAY_X*i/5, DISPLAY_Y, DISPLAY_X*i/5, DISPLAY_Y+14);
321     for (i=2; i<6; i++) {
322     XDrawLine(display, mywin, led_gc, DISPLAY_X*i/5-23, DISPLAY_Y+11, DISPLAY_X*i/5-9, DISPLAY_Y+11);
323     XDrawLine(display, mywin, led_gc, DISPLAY_X*i/5-9, DISPLAY_Y+11, DISPLAY_X*i/5-9, DISPLAY_Y+5);
324     }
325    
326     XSetForeground(display, led_gc, shadow_gray.pixel);
327     XDrawLine(display, mywin, led_gc, 0, DISPLAY_Y+15, DISPLAY_X-1, DISPLAY_Y+15);
328     for (i=1; i<6; i++)
329     XDrawLine(display, mywin, led_gc, DISPLAY_X*i/5-1, DISPLAY_Y+1, DISPLAY_X*i/5-1, DISPLAY_Y+15);
330     for (i=2; i<6; i++) {
331     XDrawLine(display, mywin, led_gc, DISPLAY_X*i/5-24, DISPLAY_Y+11, DISPLAY_X*i/5-24, DISPLAY_Y+4);
332     XDrawLine(display, mywin, led_gc, DISPLAY_X*i/5-24, DISPLAY_Y+4, DISPLAY_X*i/5-9, DISPLAY_Y+4);
333     }
334    
335     for (i=0; i<4; i++) {
336     sprintf(str, "Drive %d", i+8);
337     XSetForeground(display, led_gc, black.pixel);
338     XDrawString(display, mywin, led_gc, DISPLAY_X*(i+1)/5+8, DISPLAY_Y+12, str, strlen(str));
339     draw_led(i, LED_OFF);
340     }
341    
342     // Start timer for LED error blinking
343     c64_disp = this;
344     pulse_sa.sa_handler = (void (*)(int))pulse_handler;
345 cebix 1.3 pulse_sa.sa_flags = SA_RESTART;
346 cebix 1.1 sigemptyset(&pulse_sa.sa_mask);
347     sigaction(SIGALRM, &pulse_sa, NULL);
348     pulse_tv.it_interval.tv_sec = 0;
349     pulse_tv.it_interval.tv_usec = 400000;
350     pulse_tv.it_value.tv_sec = 0;
351     pulse_tv.it_value.tv_usec = 400000;
352     setitimer(ITIMER_REAL, &pulse_tv, NULL);
353     }
354    
355    
356     /*
357     * Display destructor
358     */
359    
360     C64Display::~C64Display()
361     {
362     XAutoRepeatOn(display);
363     XSync(display, 0);
364     }
365    
366    
367     /*
368     * Prefs may have changed
369     */
370    
371     void C64Display::NewPrefs(Prefs *prefs)
372     {
373     }
374    
375    
376     /*
377     * Connect to X server and open window
378     */
379    
380     int init_graphics(void)
381     {
382     int i;
383     char *display_name = 0;
384     XSetWindowAttributes wattr;
385     XSizeHints *hints;
386     XColor exact_color;
387     int pixbytes;
388    
389     display = XOpenDisplay(display_name);
390     if (display == 0) {
391     fprintf(stderr, "Can't connect to X server %s\n", XDisplayName(display_name));
392     return 0;
393     }
394    
395     screen = XDefaultScreen(display);
396     rootwin = XRootWindow(display, screen);
397     if (XMatchVisualInfo(display, screen, 8, PseudoColor, &visualInfo)) {
398     /* for our HP boxes */
399     } else if (XMatchVisualInfo(display, screen, 8, GrayScale, &visualInfo)) {
400     } else {
401     fprintf(stderr, "Can't obtain appropriate X visual\n");
402     return 0;
403     }
404    
405     vis = visualInfo.visual;
406     bitdepth = visualInfo.depth;
407     pixbytes = (bitdepth == 24 || bitdepth == 32 ? 4 : bitdepth == 12 || bitdepth == 16 ? 2 : 1);
408     fprintf(stderr, "Using %d bit visual\n", bitdepth);
409    
410     hsize = (DISPLAY_X + 3) & ~3;
411    
412     #if defined(X_USE_SHM)
413     img = XShmCreateImage(display, vis, bitdepth, ZPixmap, 0, &shminfo,
414     hsize, DISPLAY_Y);
415    
416     shminfo.shmid = shmget(IPC_PRIVATE, DISPLAY_Y * img->bytes_per_line,
417     IPC_CREAT | 0777);
418     shminfo.shmaddr = img->data = bufmem = (char *)shmat(shminfo.shmid, 0, 0);
419     shminfo.readOnly = False;
420     XShmAttach(display, &shminfo);
421     XSync(display,0);
422     /* now deleting means making it temporary */
423     shmctl(shminfo.shmid, IPC_RMID, 0);
424     #else
425     bufmem = (char *)malloc(pixbytes * hsize * DISPLAY_Y);
426     img = XCreateImage(display, vis, bitdepth, ZPixmap, 0, bufmem, hsize, DISPLAY_Y, 32, 0);
427     #endif
428    
429     cmap = XCreateColormap(display, rootwin, vis, AllocNone);
430    
431     XParseColor(display, cmap, "#000000", &black);
432     if (!XAllocColor(display, cmap, &black))
433     fprintf(stderr, "Whoops??\n");
434    
435     wattr.event_mask = eventmask;
436     wattr.background_pixel = black.pixel;
437     wattr.backing_store = Always;
438     wattr.backing_planes = bitdepth;
439     wattr.border_pixmap = None;
440     wattr.border_pixel = black.pixel;
441     wattr.colormap = cmap;
442    
443     mywin = XCreateWindow(display, rootwin, 0, 0, DISPLAY_X, DISPLAY_Y + 16, 0,
444     bitdepth, InputOutput, vis,
445     CWEventMask|CWBackPixel|CWBorderPixel|CWBackingStore
446     |CWBackingPlanes|CWColormap,
447     &wattr);
448     XMapWindow(display, mywin);
449     XStoreName(display, mywin, "Frodo");
450    
451     if ((hints = XAllocSizeHints()) != NULL) {
452     hints->min_width = DISPLAY_X;
453     hints->max_width = DISPLAY_X;
454     hints->min_height = DISPLAY_Y + 16;
455     hints->max_height = DISPLAY_Y + 16;
456     hints->flags = PMinSize | PMaxSize;
457     XSetWMNormalHints(display, mywin, hints);
458     XFree((char *)hints);
459     }
460    
461     black_gc = XCreateGC(display,mywin, 0, 0);
462     XSetForeground(display, black_gc, black.pixel);
463    
464     // Allocate colors for speedometer/LEDs
465     if (!XAllocNamedColor(display, cmap, "rgb:d0/d0/d0", &fill_gray, &exact_color))
466     return 0;
467     if (!XAllocNamedColor(display, cmap, "rgb:e8/e8/e8", &shine_gray, &exact_color))
468     return 0;
469     if (!XAllocNamedColor(display, cmap, "rgb:98/98/98", &shadow_gray, &exact_color))
470     return 0;
471     if (!XAllocNamedColor(display, cmap, "rgb:f0/00/00", &red, &exact_color))
472     return 0;
473     if (!XAllocNamedColor(display, cmap, "rgb:00/f0/00", &green, &exact_color))
474     return 0;
475    
476     // Load font for speedometer/LED labels
477     led_font = XLoadFont(display, "-*-helvetica-medium-r-*-*-10-*");
478    
479     for(i=0; i<256; i++)
480     keystate[i] = 0;
481    
482     return 1;
483     }
484    
485    
486     /*
487     * Redraw bitmap
488     */
489    
490     void C64Display::Update(void)
491     {
492     // Update C64 display
493     XSync(display, 0);
494     #if defined(X_USE_SHM)
495     XShmPutImage(display, mywin, black_gc, img, 0, 0, 0, 0, DISPLAY_X, DISPLAY_Y, 0);
496     #else
497     XPutImage(display, mywin, black_gc, img, 0, 0, 0, 0, DISPLAY_X, DISPLAY_Y);
498     #endif
499    
500     // Update drive LEDs
501     for (int i=0; i<4; i++)
502     if (led_state[i] != old_led_state[i]) {
503     draw_led(i, led_state[i]);
504     old_led_state[i] = led_state[i];
505     }
506     }
507    
508    
509     /*
510     * Draw one drive LED
511     */
512    
513     void C64Display::draw_led(int num, int state)
514     {
515     switch (state) {
516     case LED_OFF:
517     case LED_ERROR_OFF:
518     XSetForeground(display, led_gc, black.pixel);
519     break;
520     case LED_ON:
521     XSetForeground(display, led_gc, green.pixel);
522     break;
523     case LED_ERROR_ON:
524     XSetForeground(display, led_gc, red.pixel);
525     break;
526     }
527     XFillRectangle(display, mywin, led_gc, DISPLAY_X*(num+2)/5-23, DISPLAY_Y+5, 14, 6);
528     }
529    
530    
531     /*
532     * LED error blink
533     */
534    
535     void C64Display::pulse_handler(...)
536     {
537     for (int i=0; i<4; i++)
538     switch (c64_disp->led_state[i]) {
539     case LED_ERROR_ON:
540     c64_disp->led_state[i] = LED_ERROR_OFF;
541     break;
542     case LED_ERROR_OFF:
543     c64_disp->led_state[i] = LED_ERROR_ON;
544     break;
545     }
546     }
547    
548    
549     /*
550     * Draw speedometer
551     */
552    
553     void C64Display::Speedometer(int speed)
554     {
555     static int delay = 0;
556    
557     if (delay >= 20) {
558     char str[16];
559     sprintf(str, "%d%%", speed);
560     XSetForeground(display, led_gc, fill_gray.pixel);
561     XFillRectangle(display,mywin, led_gc, 1, DISPLAY_Y+1, DISPLAY_X/5-2, 14);
562     XSetForeground(display, led_gc, black.pixel);
563     XDrawString(display, mywin, led_gc, 24, DISPLAY_Y+12, str, strlen(str));
564     delay = 0;
565     } else
566     delay++;
567     }
568    
569    
570     /*
571     * Return pointer to bitmap data
572     */
573    
574     uint8 *C64Display::BitmapBase(void)
575     {
576     return (uint8 *)bufmem;
577     }
578    
579    
580     /*
581     * Return number of bytes per row
582     */
583    
584     int C64Display::BitmapXMod(void)
585     {
586     return hsize;
587     }
588    
589    
590     /*
591     * Poll the keyboard
592     */
593    
594     void C64Display::PollKeyboard(uint8 *key_matrix, uint8 *rev_matrix, uint8 *joystick)
595     {
596     static bool auto_rep = true;
597     for(;;) {
598     XEvent event;
599     if (!XCheckMaskEvent(display, eventmask, &event))
600     break;
601    
602     switch(event.type) {
603    
604     case KeyPress: {
605     int kc = keycode2c64((XKeyEvent *)&event);
606     if (kc == -1)
607     break;
608     switch (kc) {
609    
610     case KEY_F9: // F9: Invoke SAM
611     SAM(TheC64);
612     break;
613    
614     case KEY_F10: // F10: Quit
615     quit_requested = true;
616     break;
617    
618     case KEY_F11: // F11: NMI (Restore)
619     TheC64->NMI();
620     break;
621    
622     case KEY_F12: // F12: Reset
623     TheC64->Reset();
624     break;
625    
626     case KEY_NUM_LOCK: // NumLock: Toggle joyport
627     num_locked = true;
628     break;
629    
630     case KEY_FIRE:
631     joystate &= ~0x10;
632     break;
633     case KEY_JD:
634     joystate &= ~0x02;
635     break;
636     case KEY_JU:
637     joystate &= ~0x01;
638     break;
639     case KEY_JL:
640     joystate &= ~0x04;
641     break;
642     case KEY_JR:
643     joystate &= ~0x08;
644     break;
645     case KEY_JUL:
646     joystate &= ~0x05;
647     break;
648     case KEY_JUR:
649     joystate &= ~0x09;
650     break;
651     case KEY_JDL:
652     joystate &= ~0x06;
653     break;
654     case KEY_JDR:
655     joystate &= ~0x0a;
656     break;
657    
658     case KEY_KP_PLUS: // '+' on keypad: Increase SkipFrames
659     ThePrefs.SkipFrames++;
660     break;
661    
662     case KEY_KP_MINUS: // '-' on keypad: Decrease SkipFrames
663     if (ThePrefs.SkipFrames > 1)
664     ThePrefs.SkipFrames--;
665     break;
666    
667     case KEY_KP_MULT: // '*' on keypad: Toggle speed limiter
668     ThePrefs.LimitSpeed = !ThePrefs.LimitSpeed;
669     break;
670    
671     default:
672     if (keystate[kc])
673     break;
674     keystate[kc] = 1;
675     int c64_byte, c64_bit, shifted;
676     c64_byte = kc >> 3;
677     c64_bit = kc & 7;
678     shifted = kc & 128;
679     c64_byte &= 7;
680     if (shifted) {
681     key_matrix[6] &= 0xef;
682     rev_matrix[4] &= 0xbf;
683     }
684     key_matrix[c64_byte] &= ~(1 << c64_bit);
685     rev_matrix[c64_bit] &= ~(1 << c64_byte);
686     break;
687     }
688     break;
689     }
690    
691     case KeyRelease: {
692     int kc = keycode2c64((XKeyEvent *)&event);
693     if (kc == -1)
694     break;
695     switch (kc) {
696    
697     case KEY_NUM_LOCK:
698     num_locked = false;
699     break;
700    
701     case KEY_FIRE:
702     joystate |= 0x10;
703     break;
704     case KEY_JD:
705     joystate |= 0x02;
706     break;
707     case KEY_JU:
708     joystate |= 0x01;
709     break;
710     case KEY_JL:
711     joystate |= 0x04;
712     break;
713     case KEY_JR:
714     joystate |= 0x08;
715     break;
716     case KEY_JUL:
717     joystate |= 0x05;
718     break;
719     case KEY_JUR:
720     joystate |= 0x09;
721     break;
722     case KEY_JDL:
723     joystate |= 0x06;
724     break;
725     case KEY_JDR:
726     joystate |= 0x0a;
727     break;
728    
729     default:
730     if (!keystate[kc])
731     break;
732     keystate[kc] = 0;
733     int c64_byte, c64_bit, shifted;
734     c64_byte = kc >> 3;
735     c64_bit = kc & 7;
736     shifted = kc & 128;
737     c64_byte &= 7;
738     if (shifted) {
739     key_matrix[6] |= 0x10;
740     rev_matrix[4] |= 0x40;
741     }
742     key_matrix[c64_byte] |= (1 << c64_bit);
743     rev_matrix[c64_bit] |= (1 << c64_byte);
744     break;
745     }
746     }
747    
748     case FocusIn:
749     if (auto_rep) {
750     XAutoRepeatOff(display);
751     auto_rep = false;
752     }
753     break;
754    
755     case FocusOut:
756     if (!auto_rep) {
757     XAutoRepeatOn(display);
758     auto_rep = true;
759     }
760     break;
761     }
762     }
763     *joystick = joystate;
764     }
765    
766    
767     /*
768     * Check if NumLock is down (for switching the joystick keyboard emulation)
769     */
770    
771     bool C64Display::NumLock(void)
772     {
773     return num_locked;
774     }
775    
776    
777     /*
778     * Allocate C64 colors
779     */
780    
781     void C64Display::InitColors(uint8 *colors)
782     {
783     int i;
784     XColor col;
785     char str[20];
786    
787     for (i=0; i< 256; i++) {
788     sprintf(str, "rgb:%x/%x/%x", palette_red[i & 0x0f], palette_green[i & 0x0f], palette_blue[i & 0x0f]);
789     XParseColor(display, cmap, str, &col);
790     if (XAllocColor(display, cmap, &col))
791     colors[i] = col.pixel;
792     else
793     fprintf(stderr, "Couldn't get all colors\n");
794     }
795     }
796    
797    
798     /*
799     * Show a requester (error message)
800     */
801    
802     long int ShowRequester(char *a,char *b,char *)
803     {
804     printf("%s: %s\n", a, b);
805     return 1;
806     }