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

# Content
1 /*
2 * Display_x.h - C64 graphics display, emulator window handling,
3 * X specific stuff
4 *
5 * Frodo (C) 1994-1997,2002-2003 Christian Bauer
6 *
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 pulse_sa.sa_flags = SA_RESTART;
346 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 }