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