|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * X interface
5: *
6: * Copyright 1995, 1996 Bernd Schmidt
7: * Copyright 1996 Ed Hanway, Andre Beck, Samuel Devulder, Bruno Coste
1.1.1.2 ! root 8: * DGA support by Kai Kollmorgen
1.1 root 9: */
10:
11: #include "sysconfig.h"
12: #include "sysdeps.h"
13:
14: #include <X11/Xlib.h>
15: #include <X11/Xutil.h>
16: #include <X11/keysym.h>
17: #include <X11/cursorfont.h>
18:
19: #ifndef DONT_WANT_SHM
20: #include <sys/ipc.h>
21: #include <sys/shm.h>
22: #include <X11/extensions/XShm.h>
23: #endif
24:
25: #include <ctype.h>
26: #include <signal.h>
27:
28: #include "config.h"
29: #include "options.h"
30: #include "memory.h"
31: #include "custom.h"
1.1.1.2 ! root 32: #include "readcpu.h"
1.1 root 33: #include "newcpu.h"
34: #include "xwin.h"
35: #include "keyboard.h"
36: #include "keybuf.h"
37: #include "gui.h"
38: #include "debug.h"
39:
1.1.1.2 ! root 40: #ifdef USE_DGA_EXTENSION
! 41: #include <X11/extensions/xf86dga.h>
! 42: #define DGA_MINMAJOR 0
! 43: #define DGA_MINMINOR 0
! 44: #endif
! 45:
1.1 root 46: #ifdef __cplusplus
47: static RETSIGTYPE sigbrkhandler(...)
48: #else
49: static RETSIGTYPE sigbrkhandler(int foo)
50: #endif
51: {
52: activate_debugger();
53:
54: #if !defined(__unix) || defined(__NeXT__)
55: signal(SIGINT, sigbrkhandler);
56: #endif
57: }
58:
59: void setup_brkhandler(void)
60: {
61: #if defined(__unix) && !defined(__NeXT__)
62: struct sigaction sa;
63: sa.sa_handler = sigbrkhandler;
64: sa.sa_flags = 0;
65: #ifdef SA_RESTART
66: sa.sa_flags = SA_RESTART;
67: #endif
68: sigemptyset(&sa.sa_mask);
69: sigaction(SIGINT, &sa, NULL);
70: #else
71: signal(SIGINT, sigbrkhandler);
72: #endif
73: }
74:
1.1.1.2 ! root 75: #ifdef USE_DGA_EXTENSION
! 76: static char *fb_addr;
! 77: static int fb_width;
! 78: #endif
! 79:
1.1 root 80: static Display *display;
81: static int screen;
82: static Window rootwin, mywin;
83:
84: static GC whitegc,blackgc;
85: static XColor black,white;
86: static Colormap cmap;
87:
88: static int need_dither;
89:
90: static int autorepeatoff = 0;
91: static char *image_mem;
92: static XImage *img;
93: static Visual *vis;
94: static XVisualInfo visualInfo;
95: static int bitdepth, bit_unit;
96: #ifndef DONT_WANT_SHM
97: static int use_shm = 1;
98: static XShmSegmentInfo shminfo;
99: #endif
100: static Cursor blankCursor, xhairCursor;
101: static int cursorOn;
102:
103: #ifdef LOW_BANDWIDTH
104: static int use_low_bandwidth = 1;
105: #else
106: static int use_low_bandwidth = 0;
107: #endif
108:
1.1.1.2 ! root 109: static int x11_init_ok;
! 110:
1.1 root 111: xcolnr xcolors[4096];
112:
113: /* Keyboard and mouse */
114:
115: static int keystate[256];
116:
117: int buttonstate[3];
118: int lastmx, lastmy;
119: int newmousecounters;
120:
121: static int inwindow;
122: const long int eventmask = (KeyPressMask|KeyReleaseMask|ButtonPressMask
123: |ButtonReleaseMask|PointerMotionMask
1.1.1.2 ! root 124: #ifndef USE_DGA_EXTENSION
1.1 root 125: |FocusChangeMask|EnterWindowMask
126: |ExposureMask
1.1.1.2 ! root 127: |LeaveWindowMask
! 128: #endif
! 129: );
1.1 root 130:
131: static char *oldpixbuf;
132:
133: struct vidbuf_description gfxvidinfo;
134:
135: void flush_line(int y)
136: {
1.1.1.2 ! root 137: #ifdef USE_DGA_EXTENSION
! 138: if (need_dither) {
! 139: char *addr = gfxvidinfo.bufmem + y*gfxvidinfo.rowbytes;
! 140: DitherLine(fb_addr + fb_width*y,(UWORD *)addr,0,y,
! 141: gfx_requested_width, bit_unit);
! 142: }
! 143: #else
1.1 root 144: int xs = 0, xe;
145: int len, factor;
146: char *linebuf = y*gfxvidinfo.rowbytes + gfxvidinfo.bufmem;
147: char *src, *dst;
1.1.1.2 ! root 148:
! 149: xe = gfxvidinfo.maxlinetoscr-1;
1.1 root 150:
151: if (!use_low_bandwidth)
152: fprintf(stderr, "Bug!\n");
153:
154: switch(gfxvidinfo.pixbytes) {
155: case 4:
156: {
157: int *newp = (int *)linebuf;
158: int *oldp = (int *)(oldpixbuf + y*gfxvidinfo.rowbytes);
159: while (newp[xs] == oldp[xs]) {
160: if (xs == xe)
161: return;
162: xs++;
163: }
164: while (newp[xe] == oldp[xe]) xe--;
165:
166: dst = (char *)(oldp + xs); src = (char *)(newp + xs);
167: }
168: break;
169: case 2:
170: {
171: short *newp = (short *)linebuf;
172: short *oldp = (short *)(oldpixbuf + y*gfxvidinfo.rowbytes);
173: while (newp[xs] == oldp[xs]) {
174: if (xs == xe)
175: return;
176: xs++;
177: }
178: while (newp[xe] == oldp[xe]) xe--;
179:
180: dst = (char *)(oldp + xs); src = (char *)(newp + xs);
181: }
182: break;
183: case 1:
184: {
185: char *newp = (char *)linebuf;
186: char *oldp = (char *)(oldpixbuf + y*gfxvidinfo.rowbytes);
187: while (newp[xs] == oldp[xs]) {
188: if (xs == xe)
189: return;
190: xs++;
191: }
192: while (newp[xe] == oldp[xe]) xe--;
193:
194: dst = (char *)(oldp + xs); src = (char *)(newp + xs);
195: }
196: break;
197:
198: default:
199: abort();
200: break;
201: }
202:
203: len = xe - xs + 1;
204: memcpy (dst, src, len * gfxvidinfo.pixbytes);
205:
206: if (need_dither) {
207: UBYTE *target = (UBYTE *)image_mem + img->bytes_per_line * y;
208: xs &= ~(8/bit_unit - 1);
209: len = xe - xs + 1;
210: len += 3; len &= ~3;
211: len += (8/bit_unit - 1); len &= ~(8/bit_unit-1);
212: if (len & 3)
213: printf("%d\n",len);
214: DitherLine(target + xs*bit_unit/8, (UWORD *)linebuf + xs, xs, y, len, bit_unit);
215: }
1.1.1.2 ! root 216:
1.1 root 217: #ifndef DONT_WANT_SHM
218: if (use_shm)
219: XShmPutImage(display, mywin, blackgc, img, xs, y, xs, y, len, 1, 0);
220: else
221: #endif
222: XPutImage(display, mywin, blackgc, img, xs, y, xs, y, len, 1);
1.1.1.2 ! root 223:
! 224: #endif
1.1 root 225: }
226:
227: void flush_block (int ystart, int ystop)
228: {
1.1.1.2 ! root 229: #ifdef USE_DGA_EXTENSION
! 230: #else
1.1 root 231: int len, xs = 0;
232:
1.1.1.2 ! root 233: len = gfxvidinfo.maxlinetoscr;
1.1 root 234: #ifndef DONT_WANT_SHM
235: if (use_shm)
236: XShmPutImage(display, mywin, blackgc, img, xs, ystart, 0, ystart, len,
237: ystop - ystart + 1, 0);
238: else
239: #endif
240: XPutImage(display, mywin, blackgc, img, xs, ystart, 0, ystart, len,
241: ystop - ystart + 1);
1.1.1.2 ! root 242: #endif
1.1 root 243: }
244:
245: void flush_screen (int ystart, int ystop)
246: {
1.1.1.2 ! root 247: #ifdef USE_DGA_EXTENSION
! 248: #else
1.1 root 249: #ifndef DONT_WANT_SHM
250: if (use_shm) XSync(display, 0);
251: #endif
1.1.1.2 ! root 252: #endif
1.1 root 253: }
254:
255: static __inline__ int bitsInMask(unsigned long mask)
256: {
257: /* count bits in mask */
258: int n = 0;
259: while(mask) {
260: n += mask&1;
261: mask >>= 1;
262: }
263: return n;
264: }
265:
266: static __inline__ int maskShift(unsigned long mask)
267: {
268: /* determine how far mask is shifted */
269: int n = 0;
270: while(!(mask&1)) {
271: n++;
272: mask >>= 1;
273: }
274: return n;
275: }
276:
277: static int get_color(int r, int g, int b, xcolnr *cnp)
278: {
279: XColor col;
280: char str[10];
281: sprintf(str, "rgb:%x/%x/%x", r, g, b);
282: XParseColor(display, cmap, str, &col);
283: if (XAllocColor(display, cmap, &col)) {
284: *cnp = col.pixel;
285: return 1;
286: }
287: return 0;
288: }
289:
290: static int init_colors(void)
291: {
292: if (need_dither) {
293: if (bitdepth == 1)
294: setup_greydither (1, get_color);
295: else
296: setup_dither (bitdepth, get_color);
297: return 1;
298: }
299:
300: if (bitdepth != 8 && bitdepth != 12
301: && bitdepth != 16 && bitdepth != 24) {
302: fprintf(stderr, "Unsupported bit depth (%d)\n", bitdepth);
303: return 0;
304: }
305:
306: #ifdef __cplusplus
307: switch(visualInfo.c_class)
308: #else
309: switch(visualInfo.class)
310: #endif
311: {
312: case TrueColor:
313: {
314: int red_bits = bitsInMask(visualInfo.red_mask);
315: int green_bits = bitsInMask(visualInfo.green_mask);
316: int blue_bits = bitsInMask(visualInfo.blue_mask);
317: int red_shift = maskShift(visualInfo.red_mask);
318: int green_shift = maskShift(visualInfo.green_mask);
319: int blue_shift = maskShift(visualInfo.blue_mask);
320: alloc_colors64k(red_bits, green_bits, blue_bits, red_shift,
321: green_shift, blue_shift);
322: }
323: break;
324:
325: case GrayScale:
326: case PseudoColor:
327: alloc_colors256(get_color);
328: break;
329:
330: default:
331: #ifdef __cplusplus
332: fprintf(stderr, "Unsupported visual class (%d)\n", visualInfo.c_class);
333: #else
334: fprintf(stderr, "Unsupported visual class (%d)\n", visualInfo.class);
335: #endif
336: return 0;
337: }
338: return 1;
339: }
340:
341: int graphics_init(void)
342: {
343: int i,j;
344: char *display_name = 0;
345: XSetWindowAttributes wattr;
346: XPixmapFormatValues *xpfvs;
1.1.1.2 ! root 347: #ifdef USE_DGA_EXTENSION
! 348: int MajorVersion, MinorVersion;
! 349: int EventBase, ErrorBase;
! 350: int fb_bank, fb_banks, fb_mem;
! 351: #endif
! 352:
! 353: x11_init_ok = 0;
1.1 root 354: need_dither = 0;
1.1.1.2 ! root 355:
! 356: #ifdef USE_DGA_EXTENSION
! 357: if (geteuid()) {
! 358: fprintf(stderr, "You must be root to use UAE with the DGA extensions.\n");
! 359: return(0);
1.1 root 360: }
1.1.1.2 ! root 361: #endif
1.1 root 362:
363: display = XOpenDisplay(display_name);
364: if (display == 0) {
365: fprintf(stderr, "Can't connect to X server %s\n", XDisplayName(display_name));
366: return 0;
367: }
1.1.1.2 ! root 368:
! 369: #ifdef USE_DGA_EXTENSION
! 370: if (!XF86DGAQueryVersion(display, &MajorVersion, &MinorVersion)) {
! 371: fprintf(stderr, "Unable to query video extension version\n");
! 372: return(0);
! 373: }
! 374:
! 375: if (!XF86DGAQueryExtension(display, &EventBase, &ErrorBase)) {
! 376: fprintf(stderr, "Unable to query video extension information\n");
! 377: return(0);
! 378: }
! 379:
! 380: /* Fail if the extension version in the server is too old */
! 381: if (MajorVersion < DGA_MINMAJOR ||
! 382: (MajorVersion == DGA_MINMAJOR && MinorVersion < DGA_MINMINOR)) {
! 383: fprintf(stderr,
! 384: "Xserver is running an old XFree86-DGA version"
! 385: " (%d.%d)\n", MajorVersion, MinorVersion);
! 386: fprintf(stderr, "Minimum required version is %d.%d\n",
! 387: DGA_MINMAJOR, DGA_MINMINOR);
! 388: return(0);
! 389: }
! 390: #endif
! 391:
1.1 root 392: screen = XDefaultScreen(display);
393: rootwin = XRootWindow(display,screen);
394:
395: /* try for a 12 bit visual first, then a 16 bit, then a 24 bit, then 8 bit */
396: if (XMatchVisualInfo(display, screen, 12, TrueColor, &visualInfo)) {
397: } else if (XMatchVisualInfo(display, screen, 16, TrueColor, &visualInfo)) {
398: } else if (XMatchVisualInfo(display, screen, 24, TrueColor, &visualInfo)) {
399: } else if (XMatchVisualInfo(display, screen, 8, PseudoColor, &visualInfo)) {
400: /* for our HP boxes */
401: } else if (XMatchVisualInfo(display, screen, 8, GrayScale, &visualInfo)) {
402: } else if (XMatchVisualInfo(display, screen, 4, PseudoColor, &visualInfo)) {
403: /* VGA16 server. Argh. */
404: } else if (XMatchVisualInfo(display, screen, 1, StaticGray, &visualInfo)) {
405: /* Mono server. Yuk */
406: } else {
407: fprintf(stderr, "Can't obtain appropriate X visual.\n");
408: return 0;
409: }
410: vis = visualInfo.visual;
411: bitdepth = visualInfo.depth;
412:
413: /* We now have the bitdepth of the display, but that doesn't tell us yet
414: * how many bits to use per pixel. The VGA16 server has a bitdepth of 4,
415: * but uses 1 byte per pixel. */
416: xpfvs = XListPixmapFormats(display, &i);
417: for (j = 0; j < i && xpfvs->depth != bitdepth; j++, xpfvs++)
418: ;
419: if (j == i) {
420: fprintf(stderr, "Your X server is feeling ill.\n");
421: return 0;
422: }
423:
424: bit_unit = xpfvs->bits_per_pixel;
425: fprintf(stderr, "Using %d bit visual, %d bits per pixel\n", bitdepth, bit_unit);
426:
1.1.1.2 ! root 427: if (gfx_requested_width < 320)
! 428: gfx_requested_width = 320;
! 429: if (gfx_requested_height < 200)
! 430: gfx_requested_height = 200;
! 431: if (gfx_requested_height > 300 && ! gfx_requested_linedbl)
! 432: gfx_requested_height = 300;
! 433: if (gfx_requested_height > 600)
! 434: gfx_requested_height = 600;
! 435:
! 436: gfx_requested_width += 7; /* X86.S wants multiples of 4 bytes, might be 8 in the future. */
! 437: gfx_requested_width &= ~7;
! 438:
! 439: gfxvidinfo.maxlinetoscr = gfx_requested_width;
! 440: gfxvidinfo.maxline = gfx_requested_height;
1.1 root 441:
442: cmap = XCreateColormap(display, rootwin, vis, AllocNone);
443: XParseColor(display, cmap, "#000000", &black);
444: if (!XAllocColor(display, cmap, &black))
445: fprintf(stderr, "Whoops??\n");
446: XParseColor(display, cmap, "#ffffff", &white);
447: if (!XAllocColor(display, cmap, &white))
448: fprintf(stderr, "Whoops??\n");
449:
1.1.1.2 ! root 450: #ifdef USE_DGA_EXTENSION
! 451: wattr.override_redirect = 1;
! 452: #endif
1.1 root 453: wattr.event_mask = eventmask;
454: wattr.background_pixel = black.pixel;
455: wattr.backing_store = Always;
456: wattr.backing_planes = bitdepth;
457: wattr.border_pixmap = None;
458: wattr.border_pixel = black.pixel;
459: wattr.colormap = cmap;
1.1.1.2 ! root 460:
! 461: mywin = XCreateWindow(display, rootwin, 0, 0, gfx_requested_width, gfx_requested_height, 0,
1.1 root 462: bitdepth, InputOutput, vis,
463: CWEventMask|CWBackPixel|CWBorderPixel|CWBackingStore
1.1.1.2 ! root 464: |CWBackingPlanes|CWColormap
! 465: #ifdef USE_DGA_EXTENSION
! 466: |CWOverrideRedirect
! 467: #endif
! 468: ,&wattr);
! 469:
! 470: XMapWindow(display, mywin);
! 471: #ifdef USE_DGA_EXTENSION
! 472: XRaiseWindow(display, mywin);
! 473: #else
1.1 root 474: XStoreName(display, mywin, "UAE");
475:
476: blankCursor = XCreatePixmapCursor(display,
477: XCreatePixmap(display, mywin, 1, 1, 1),
478: XCreatePixmap(display, mywin, 1, 1, 1),
479: &black, &white, 0, 0);
480: xhairCursor = XCreateFontCursor(display, XC_crosshair);
481:
482: whitegc = XCreateGC(display,mywin,0,0);
483: blackgc = XCreateGC(display,mywin,0,0);
484:
1.1.1.2 ! root 485: XSetForeground(display, blackgc, black.pixel);
! 486: XSetForeground(display, whitegc, white.pixel);
! 487: #endif
! 488:
1.1 root 489: if (bitdepth < 8 || (bitdepth == 8 && color_mode == 3)) {
490: gfxvidinfo.pixbytes = 2;
491: use_low_bandwidth = 1;
492: need_dither = 1;
493: #ifndef DONT_WANT_SHM
494: use_shm = 0;
495: #endif
496: } else {
497: gfxvidinfo.pixbytes = (bitdepth == 24 || bitdepth == 32 ? 4
498: : bitdepth == 12 || bitdepth == 16 ? 2
499: : 1);
500: }
1.1.1.2 ! root 501:
! 502: #ifdef USE_DGA_EXTENSION
! 503: /* We want all the key presses */
! 504:
! 505: XGrabKeyboard(display, rootwin, 1, GrabModeAsync,
! 506: GrabModeAsync, CurrentTime);
! 507:
! 508: /* and all the mouse moves */
! 509: XGrabPointer(display, rootwin, 1, PointerMotionMask |
! 510: ButtonPressMask | ButtonReleaseMask,
! 511: GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
! 512:
! 513: XF86DGAGetVideo(display, screen,&fb_addr,&fb_width,&fb_bank,&fb_mem);
! 514: fprintf(stderr, "addr:%X, width %d, bank size %d mem size %d\n",
! 515: fb_addr, fb_width, fb_bank,fb_mem);
! 516:
! 517: if (fb_bank<fb_mem)
! 518: fprintf(stderr,"banksize < memsize, must use XF86DGASetVidPage !\n");
! 519:
! 520: XF86DGADirectVideo(display, screen,
! 521: XF86DGADirectGraphics|
! 522: XF86DGADirectMouse|
! 523: XF86DGADirectKeyb);
! 524: setuid(getuid());
! 525:
! 526: XF86DGASetViewPort(display, screen, 0, 0);
! 527: #else
1.1 root 528:
529: #ifndef DONT_WANT_SHM
530: if (use_shm) {
1.1.1.2 ! root 531: img = XShmCreateImage(display, vis, bitdepth, ZPixmap, 0, &shminfo, gfx_requested_width, gfx_requested_height);
1.1 root 532:
1.1.1.2 ! root 533: shminfo.shmid = shmget(IPC_PRIVATE, gfx_requested_height * img->bytes_per_line,
1.1 root 534: IPC_CREAT | 0777);
535: shminfo.shmaddr = img->data = image_mem = (char *)shmat(shminfo.shmid, 0, 0);
536: shminfo.readOnly = False;
537: /* let the xserver attach */
538: XShmAttach(display, &shminfo);
539: XSync(display,0);
540: /* now deleting means making it temporary */
541: shmctl(shminfo.shmid, IPC_RMID, 0);
542: } else
543: #endif
544: {
545: /* Question for people who know about X: Could we allocate the buffer
546: * after creating the image and then do img->data = buffer, as above in
547: * the SHM case?
548: */
1.1.1.2 ! root 549: image_mem = (char *)malloc(gfx_requested_height * gfx_requested_width * bit_unit / 8); /* ??? */
1.1 root 550: img = XCreateImage(display, vis, bitdepth, ZPixmap, 0, image_mem,
1.1.1.2 ! root 551: gfx_requested_width, gfx_requested_height, 32, 0);
! 552: if (img->bytes_per_line != gfx_requested_width * bit_unit / 8)
1.1 root 553: fprintf (stderr, "Possible bug here... graphics may look strange.\n");
554: }
1.1.1.2 ! root 555: #endif
1.1 root 556:
557: if (need_dither) {
1.1.1.2 ! root 558: gfxvidinfo.rowbytes = gfxvidinfo.pixbytes * gfx_requested_width;
! 559: gfxvidinfo.bufmem = (char *)malloc(gfxvidinfo.rowbytes * gfx_requested_height);
1.1 root 560: } else {
1.1.1.2 ! root 561: #ifdef USE_DGA_EXTENSION
! 562: gfxvidinfo.rowbytes = fb_width*gfxvidinfo.pixbytes;
! 563: gfxvidinfo.bufmem = fb_addr;
! 564: #else
1.1 root 565: gfxvidinfo.rowbytes = img->bytes_per_line;
566: gfxvidinfo.bufmem = image_mem;
1.1.1.2 ! root 567: #endif
1.1 root 568: }
569:
570: if (use_low_bandwidth) {
571: gfxvidinfo.maxblocklines = 0;
1.1.1.2 ! root 572: oldpixbuf = (char *)malloc(gfxvidinfo.rowbytes * gfx_requested_height);
1.1 root 573: } else {
574: gfxvidinfo.maxblocklines = 100; /* whatever... */
575: }
576:
577: if (!init_colors())
578: return 0;
579:
580: buttonstate[0] = buttonstate[1] = buttonstate[2] = 0;
581: for(i=0; i<256; i++)
582: keystate[i] = 0;
583:
584: lastmx = lastmy = 0;
585: newmousecounters = 0;
586: inwindow = 0;
1.1.1.2 ! root 587:
! 588: #ifndef USE_DGA_EXTENSION
1.1 root 589: if (!no_xhair)
1.1.1.2 ! root 590: XDefineCursor(display, mywin, xhairCursor);
1.1 root 591: else
1.1.1.2 ! root 592: XDefineCursor(display, mywin, blankCursor);
1.1 root 593: cursorOn = 1;
1.1.1.2 ! root 594: #else
! 595: XF86DGAInstallColormap(display,screen,cmap);
! 596: #endif
! 597:
! 598: return x11_init_ok = 1;
1.1 root 599: }
600:
601: void graphics_leave(void)
602: {
1.1.1.2 ! root 603: if (!x11_init_ok)
! 604: return;
! 605:
1.1 root 606: if (autorepeatoff)
1.1.1.2 ! root 607: XAutoRepeatOn(display);
! 608: XFlush(display);
! 609: XSync(display, 0);
! 610: #ifdef USE_DGA_EXTENSION
! 611: XF86DGADirectVideo(display, DefaultScreen(display), 0);
! 612: XUngrabPointer(display, CurrentTime);
! 613: XUngrabKeyboard(display, CurrentTime);
! 614: dumpcustom();
! 615: #endif
1.1 root 616: }
617:
618: /* Decode KeySyms. This function knows about all keys that are common
619: * between different keyboard languages. */
620: static int kc_decode (KeySym ks)
621: {
622: switch (ks) {
623: case XK_B: case XK_b: return AK_B;
624: case XK_C: case XK_c: return AK_C;
625: case XK_D: case XK_d: return AK_D;
626: case XK_E: case XK_e: return AK_E;
627: case XK_F: case XK_f: return AK_F;
628: case XK_G: case XK_g: return AK_G;
629: case XK_H: case XK_h: return AK_H;
630: case XK_I: case XK_i: return AK_I;
631: case XK_J: case XK_j: return AK_J;
632: case XK_K: case XK_k: return AK_K;
633: case XK_L: case XK_l: return AK_L;
634: case XK_N: case XK_n: return AK_N;
635: case XK_O: case XK_o: return AK_O;
636: case XK_P: case XK_p: return AK_P;
637: case XK_R: case XK_r: return AK_R;
638: case XK_S: case XK_s: return AK_S;
639: case XK_T: case XK_t: return AK_T;
640: case XK_U: case XK_u: return AK_U;
641: case XK_V: case XK_v: return AK_V;
642: case XK_X: case XK_x: return AK_X;
643:
644: case XK_0: return AK_0;
645: case XK_1: return AK_1;
646: case XK_2: return AK_2;
647: case XK_3: return AK_3;
648: case XK_4: return AK_4;
649: case XK_5: return AK_5;
650: case XK_6: return AK_6;
651: case XK_7: return AK_7;
652: case XK_8: return AK_8;
653: case XK_9: return AK_9;
654:
655: /* You never know which Keysyms might be missing on some workstation
656: * This #ifdef should be enough. */
657: #if defined(XK_KP_Prior) && defined(XK_KP_Left) && defined(XK_KP_Insert) && defined (XK_KP_End)
658: case XK_KP_0: case XK_KP_Insert: return AK_NP0;
659: case XK_KP_1: case XK_KP_End: return AK_NP1;
660: case XK_KP_2: case XK_KP_Down: return AK_NP2;
661: case XK_KP_3: case XK_KP_Next: return AK_NP3;
662: case XK_KP_4: case XK_KP_Left: return AK_NP4;
663: case XK_KP_5: case XK_KP_Begin: return AK_NP5;
664: case XK_KP_6: case XK_KP_Right: return AK_NP6;
665: case XK_KP_7: case XK_KP_Home: return AK_NP7;
666: case XK_KP_8: case XK_KP_Up: return AK_NP8;
667: case XK_KP_9: case XK_KP_Prior: return AK_NP9;
668: #else
669: case XK_KP_0: return AK_NP0;
670: case XK_KP_1: return AK_NP1;
671: case XK_KP_2: return AK_NP2;
672: case XK_KP_3: return AK_NP3;
673: case XK_KP_4: return AK_NP4;
674: case XK_KP_5: return AK_NP5;
675: case XK_KP_6: return AK_NP6;
676: case XK_KP_7: return AK_NP7;
677: case XK_KP_8: return AK_NP8;
678: case XK_KP_9: return AK_NP9;
679: #endif
680: case XK_KP_Divide: return AK_NPDIV;
681: case XK_KP_Multiply: return AK_NPMUL;
682: case XK_KP_Subtract: return AK_NPSUB;
683: case XK_KP_Add: return AK_NPADD;
684: case XK_KP_Decimal: return AK_NPDEL;
685: case XK_KP_Enter: return AK_ENT;
686:
687: case XK_F1: return AK_F1;
688: case XK_F2: return AK_F2;
689: case XK_F3: return AK_F3;
690: case XK_F4: return AK_F4;
691: case XK_F5: return AK_F5;
692: case XK_F6: return AK_F6;
693: case XK_F7: return AK_F7;
694: case XK_F8: return AK_F8;
695: case XK_F9: return AK_F9;
696: case XK_F10: return AK_F10;
697:
698: case XK_BackSpace: return AK_BS;
699: case XK_Delete: return AK_DEL;
700: case XK_Control_L: case XK_Control_R: return AK_CTRL;
701: case XK_Tab: return AK_TAB;
702: case XK_Alt_L: return AK_LALT;
703: case XK_Alt_R: return AK_RALT;
704: case XK_Meta_R: case XK_Hyper_R: return AK_RAMI;
705: case XK_Meta_L: case XK_Hyper_L: return AK_LAMI;
706: case XK_Return: return AK_RET;
707: case XK_space: return AK_SPC;
708: case XK_Shift_L: return AK_LSH;
709: case XK_Shift_R: return AK_RSH;
710: case XK_Escape: return AK_ESC;
711:
712: case XK_Insert: return AK_BACKSLASH;
713: case XK_End: return AK_HELP;
714: case XK_Caps_Lock: return AK_CAPSLOCK;
715:
716: case XK_Up: return AK_UP;
717: case XK_Down: return AK_DN;
718: case XK_Left: return AK_LF;
719: case XK_Right: return AK_RT;
720:
721: case XK_F11: return AK_BACKSLASH;
1.1.1.2 ! root 722: #ifdef USE_DGA_EXTENSION
! 723: case XK_F12:
! 724: regs.spcflags |= SPCFLAG_BRK;
! 725: quit_program = 1;
! 726: return(-1);
! 727: #else
1.1 root 728: case XK_F12: return AK_mousestuff;
1.1.1.2 ! root 729: #endif
1.1 root 730: #ifdef XK_F14
731: case XK_F14:
732: #endif
733: case XK_Scroll_Lock: return AK_inhibit;
734:
735: #ifdef XK_Page_Up /* These are missing occasionally */
736: case XK_Page_Up: return AK_RAMI; /* PgUp mapped to right amiga */
737: case XK_Page_Down: return AK_LAMI; /* PgDn mapped to left amiga */
738: #endif
739: }
740: return -1;
741: }
742:
743: static int decode_fr(KeySym ks)
744: {
745: switch(ks) { /* FR specific */
746: case XK_A: case XK_a: return AK_Q;
747: case XK_M: case XK_m: return AK_SEMICOLON;
748: case XK_Q: case XK_q: return AK_A;
749: case XK_Y: case XK_y: return AK_Y;
1.1.1.2 ! root 750: case XK_W: case XK_w: return AK_Z;
! 751: case XK_Z: case XK_z: return AK_W;
1.1 root 752: case XK_bracketleft: return AK_LBRACKET;
753: case XK_bracketright: return AK_RBRACKET;
754: case XK_comma: return AK_M;
755: case XK_less: case XK_greater: return AK_LTGT;
756: case XK_period: return AK_COMMA;
757: case XK_parenright: return AK_MINUS;
758: case XK_equal: return AK_SLASH;
759: case XK_numbersign: return AK_NUMBERSIGN;
760: case XK_slash: return AK_PERIOD;
761: case XK_minus: return AK_EQUAL;
762: case XK_backslash: return AK_BACKSLASH;
763: }
764:
765: return -1;
766: }
767:
768: static int decode_us(KeySym ks)
769: {
770: switch(ks) { /* US specific */
771: case XK_A: case XK_a: return AK_A;
772: case XK_M: case XK_m: return AK_M;
773: case XK_Q: case XK_q: return AK_Q;
774: case XK_Y: case XK_y: return AK_Y;
1.1.1.2 ! root 775: case XK_W: case XK_w: return AK_W;
1.1 root 776: case XK_Z: case XK_z: return AK_Z;
777: case XK_bracketleft: return AK_LBRACKET;
778: case XK_bracketright: return AK_RBRACKET;
779: case XK_comma: return AK_COMMA;
780: case XK_period: return AK_PERIOD;
781: case XK_slash: return AK_SLASH;
782: case XK_semicolon: return AK_SEMICOLON;
783: case XK_minus: return AK_MINUS;
784: case XK_equal: return AK_EQUAL;
785: /* this doesn't work: */
786: case XK_quoteright: return AK_QUOTE;
787: case XK_quoteleft: return AK_BACKQUOTE;
788: case XK_backslash: return AK_BACKSLASH;
789: }
790:
791: return -1;
792: }
793:
794: static int decode_de(KeySym ks)
795: {
796: switch(ks) {
797: /* DE specific */
798: case XK_A: case XK_a: return AK_A;
799: case XK_M: case XK_m: return AK_M;
800: case XK_Q: case XK_q: return AK_Q;
1.1.1.2 ! root 801: case XK_W: case XK_w: return AK_W;
1.1 root 802: case XK_Y: case XK_y: return AK_Z;
803: case XK_Z: case XK_z: return AK_Y;
804: case XK_Odiaeresis: case XK_odiaeresis: return AK_SEMICOLON;
805: case XK_Adiaeresis: case XK_adiaeresis: return AK_QUOTE;
806: case XK_Udiaeresis: case XK_udiaeresis: return AK_LBRACKET;
807: case XK_plus: case XK_asterisk: return AK_RBRACKET;
808: case XK_comma: return AK_COMMA;
809: case XK_period: return AK_PERIOD;
810: case XK_less: case XK_greater: return AK_LTGT;
811: case XK_numbersign: return AK_NUMBERSIGN;
812: case XK_ssharp: return AK_MINUS;
813: case XK_apostrophe: return AK_EQUAL;
814: case XK_asciicircum: return AK_BACKQUOTE;
815: case XK_minus: return AK_SLASH;
816: }
817:
818: return -1;
819: }
820:
821: static int decode_se(KeySym ks)
822: {
823: switch(ks) {
824: /* SE specific */
825: case XK_A: case XK_a: return AK_A;
826: case XK_M: case XK_m: return AK_M;
827: case XK_Q: case XK_q: return AK_Q;
1.1.1.2 ! root 828: case XK_W: case XK_w: return AK_W;
1.1 root 829: case XK_Y: case XK_y: return AK_Y;
830: case XK_Z: case XK_z: return AK_Z;
831: case XK_Odiaeresis: case XK_odiaeresis: return AK_SEMICOLON;
832: case XK_Adiaeresis: case XK_adiaeresis: return AK_QUOTE;
833: case XK_Aring: case XK_aring: return AK_LBRACKET;
834: case XK_comma: return AK_COMMA;
835: case XK_period: return AK_PERIOD;
836: case XK_minus: return AK_SLASH;
837: case XK_less: case XK_greater: return AK_LTGT;
838: case XK_plus: case XK_question: return AK_EQUAL;
839: case XK_at: case XK_onehalf: return AK_BACKQUOTE;
840: case XK_asciitilde: case XK_asciicircum: return AK_RBRACKET;
841: case XK_backslash: case XK_bar: return AK_MINUS;
842:
843: case XK_numbersign: return AK_NUMBERSIGN;
844: }
845:
846: return -1;
847: }
848:
849: static int decode_it(KeySym ks)
850: {
851: switch(ks) {
852: /* IT specific */
853: case XK_A: case XK_a: return AK_A;
854: case XK_M: case XK_m: return AK_M;
855: case XK_Q: case XK_q: return AK_Q;
1.1.1.2 ! root 856: case XK_W: case XK_w: return AK_W;
1.1 root 857: case XK_Y: case XK_y: return AK_Y;
858: case XK_Z: case XK_z: return AK_Z;
859: case XK_Ograve: case XK_ograve: return AK_SEMICOLON;
860: case XK_Agrave: case XK_agrave: return AK_QUOTE;
861: case XK_Egrave: case XK_egrave: return AK_LBRACKET;
862: case XK_plus: case XK_asterisk: return AK_RBRACKET;
863: case XK_comma: return AK_COMMA;
864: case XK_period: return AK_PERIOD;
865: case XK_less: case XK_greater: return AK_LTGT;
866: case XK_backslash: case XK_bar: return AK_BACKQUOTE;
867: case XK_apostrophe: return AK_MINUS;
868: case XK_Igrave: case XK_igrave: return AK_EQUAL;
869: case XK_minus: return AK_SLASH;
870: case XK_numbersign: return AK_NUMBERSIGN;
871: }
872:
873: return -1;
874: }
875:
1.1.1.2 ! root 876: static int decode_es(KeySym ks)
! 877: {
! 878: switch(ks) {
! 879: /* ES specific */
! 880: case XK_A: case XK_a: return AK_A;
! 881: case XK_M: case XK_m: return AK_M;
! 882: case XK_Q: case XK_q: return AK_Q;
! 883: case XK_W: case XK_w: return AK_W;
! 884: case XK_Y: case XK_y: return AK_Y;
! 885: case XK_Z: case XK_z: return AK_Z;
! 886: case XK_ntilde: case XK_Ntilde: return AK_SEMICOLON;
! 887: #ifdef XK_dead_acute
! 888: case XK_dead_acute: case XK_dead_diaeresis: return AK_QUOTE;
! 889: case XK_dead_grave: case XK_dead_circumflex: return AK_LBRACKET;
! 890: #endif
! 891: case XK_plus: case XK_asterisk: return AK_RBRACKET;
! 892: case XK_comma: return AK_COMMA;
! 893: case XK_period: return AK_PERIOD;
! 894: case XK_less: case XK_greater: return AK_LTGT;
! 895: case XK_backslash: case XK_bar: return AK_BACKQUOTE;
! 896: case XK_apostrophe: return AK_MINUS;
! 897: case XK_Igrave: case XK_igrave: return AK_EQUAL;
! 898: case XK_minus: return AK_SLASH;
! 899: case XK_numbersign: return AK_NUMBERSIGN;
! 900: }
! 901:
! 902: return -1;
! 903: }
! 904:
1.1 root 905: static int keycode2amiga(XKeyEvent *event)
906: {
907: KeySym ks;
908: int as;
909: int index = 0;
910:
911: do {
912: ks = XLookupKeysym(event, index);
913: as = kc_decode (ks);
914:
915: if (as == -1) {
916: switch(keyboard_lang) {
917:
918: case KBD_LANG_FR:
919: as = decode_fr(ks);
920: break;
921:
922: case KBD_LANG_US:
923: as = decode_us(ks);
924: break;
925:
926: case KBD_LANG_DE:
927: as = decode_de(ks);
928: break;
929:
930: case KBD_LANG_SE:
931: as = decode_se(ks);
932: break;
933:
934: case KBD_LANG_IT:
935: as = decode_it(ks);
936: break;
937:
1.1.1.2 ! root 938: case KBD_LANG_ES:
! 939: as = decode_es(ks);
! 940: break;
! 941:
1.1 root 942: default:
943: as = -1;
944: break;
945: }
946: }
947: if(-1 != as)
948: return as;
949: index++;
950: } while (ks != NoSymbol);
951: return -1;
952: }
953:
954: static struct timeval lastMotionTime;
955:
956: void handle_events(void)
957: {
958: int refresh = 0;
959: newmousecounters = 0;
960: gui_handle_events();
961:
962: for (;;) {
963: XEvent event;
964: #if 0
965: if (!XCheckMaskEvent(display, eventmask, &event)) break;
966: #endif
967: if (!XPending(display)) break;
968: XNextEvent(display, &event);
969:
970: switch(event.type) {
971: case KeyPress: {
972: int kc = keycode2amiga((XKeyEvent *)&event);
973: if (kc == -1) break;
974: switch (kc) {
975: case AK_mousestuff:
976: togglemouse();
977: break;
978:
979: case AK_inhibit:
980: inhibit_frame ^= 1;
981: break;
982:
983: default:
984: if (!keystate[kc]) {
985: keystate[kc] = 1;
986: record_key (kc << 1);
987: }
988: break;
989: }
990: break;
991: }
992: case KeyRelease: {
993: int kc = keycode2amiga((XKeyEvent *)&event);
994: if (kc == -1) break;
995: keystate[kc] = 0;
996: record_key ((kc << 1) | 1);
997: break;
998: }
999: case ButtonPress:
1000: buttonstate[((XButtonEvent *)&event)->button-1] = 1;
1001: break;
1002: case ButtonRelease:
1003: buttonstate[((XButtonEvent *)&event)->button-1] = 0;
1004: break;
1.1.1.2 ! root 1005: #ifndef USE_DGA_EXTENSION
1.1 root 1006: case EnterNotify:
1007: newmousecounters = 1;
1008: lastmx = ((XCrossingEvent *)&event)->x;
1009: lastmy = ((XCrossingEvent *)&event)->y;
1010: inwindow = 1;
1011: break;
1012: case LeaveNotify:
1013: inwindow = 0;
1014: break;
1015: case FocusIn:
1016: if (!autorepeatoff)
1017: XAutoRepeatOff(display);
1018: autorepeatoff = 1;
1019: break;
1020: case FocusOut:
1021: if (autorepeatoff)
1022: XAutoRepeatOn(display);
1023: autorepeatoff = 0;
1024: break;
1025: case MotionNotify:
1026: if (inwindow) {
1027: lastmx = ((XMotionEvent *)&event)->x;
1028: lastmy = ((XMotionEvent *)&event)->y;
1029: if(!cursorOn && !no_xhair) {
1030: XDefineCursor(display, mywin, xhairCursor);
1031: cursorOn = 1;
1032: }
1033: gettimeofday(&lastMotionTime, NULL);
1034: }
1035: break;
1036: case Expose:
1037: refresh = 1;
1038: break;
1.1.1.2 ! root 1039: #else
! 1040: case MotionNotify:
! 1041: newmousecounters = 0;
! 1042: lastmx += ((XMotionEvent *)&event)->x_root;
! 1043: lastmy += ((XMotionEvent *)&event)->y_root;
! 1044: #endif
1.1 root 1045: }
1046: }
1047:
1.1.1.2 ! root 1048: #ifndef USE_DGA_EXTENSION
1.1 root 1049: if(refresh) {
1050: #ifndef DONT_WANT_SHM
1051: if (use_shm)
1.1.1.2 ! root 1052: XShmPutImage(display, mywin, blackgc, img, 0, 0, 0, 0, gfx_requested_width, gfx_requested_height, 0);
1.1 root 1053: else
1054: #endif
1.1.1.2 ! root 1055: XPutImage(display, mywin, blackgc, img, 0, 0, 0, 0, gfx_requested_width, gfx_requested_height);
1.1 root 1056: }
1057: if(cursorOn && !no_xhair) {
1058: struct timeval now;
1059: int diff;
1060: gettimeofday(&now, NULL);
1061: diff = (now.tv_sec - lastMotionTime.tv_sec) * 1000000 +
1062: (now.tv_usec - lastMotionTime.tv_usec);
1063: if(diff > 1000000) {
1064: XDefineCursor(display, mywin, blankCursor);
1065: cursorOn = 0;
1066: }
1067: }
1.1.1.2 ! root 1068: #endif
1.1 root 1069: /* "Affengriff" */
1070: if(keystate[AK_CTRL] && keystate[AK_LAMI] && keystate[AK_RAMI])
1071: m68k_reset();
1072: }
1073:
1074: int debuggable(void)
1075: {
1076: return 1;
1077: }
1078:
1079: int needmousehack(void)
1080: {
1.1.1.2 ! root 1081: #ifdef USE_DGA_EXTENSION
! 1082: return 0;
! 1083: #else
1.1 root 1084: return 1;
1.1.1.2 ! root 1085: #endif
1.1 root 1086: }
1087:
1088: void LED(int on)
1089: {
1.1.1.2 ! root 1090: #if 0 /* Maybe that is responsible for the joystick emulation problems on SunOS? */
1.1 root 1091: static int last_on = -1;
1092: XKeyboardControl control;
1093:
1094: if (last_on == on) return;
1095: last_on = on;
1096: control.led = 1; /* implementation defined */
1097: control.led_mode = on ? LedModeOn : LedModeOff;
1098: XChangeKeyboardControl(display, KBLed | KBLedMode, &control);
1.1.1.2 ! root 1099: #endif
1.1 root 1100: }
1101:
1102: void target_specific_usage(void)
1103: {
1.1.1.2 ! root 1104: printf(" -S n : Sound emulation accuracy (n = 0, 1, 2 or 3)\n"
! 1105: " For sound emulation, n = 2 is recommended\n");
! 1106: printf(" -b n : Use n bits for sound output (8 or 16)\n");
! 1107: printf(" -R n : Use n Hz to output sound. Common values are\n"
! 1108: " 22050 Hz or 44100 Hz\n");
! 1109: printf(" -B n : Use a sound buffer of n bytes (use small\n"
! 1110: " values on fast machines)\n");
! 1111: printf(" -x : Use visible cross-hair cursor\n");
! 1112: printf(" -l lang : Set keyboard language to lang, where lang is\n"
! 1113: " DE, SE, US, FR or IT\n");
! 1114: printf(" -p command : Use command to pipe printer output to.\n");
! 1115: printf(" -I device : Name of the used serial device (i.e. /dev/ttyS1\n");
1.1 root 1116: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.