rnd-20040822-1-src
[rocksndiamonds.git] / src / game_em / init.c
1 /* 2000-08-10T18:03:54Z
2  *
3  * open X11 display and sound
4  */
5
6 #if 1
7 #include <X11/Xlib.h>
8 #include <X11/Xutil.h>
9 #include <X11/Xatom.h>
10 #include <X11/Xos.h>
11 #include <X11/Intrinsic.h>
12 #include <X11/keysymdef.h>
13 #endif
14
15 #include <X11/Xlib.h>
16 #include <X11/Xutil.h>
17 #include <X11/Xatom.h>
18 #include <X11/keysym.h>
19 #include <X11/cursorfont.h>
20 #include <X11/xpm.h>
21 #include <sys/types.h>
22 #include <sys/wait.h>
23 #include <unistd.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <signal.h>
27 #include <string.h>
28 #include <errno.h>
29
30 #include "../libgame/platform.h"
31 #include "../libgame/libgame.h"
32
33 #include "global.h"
34 #include "display.h"
35 #include "sample.h"
36
37
38 #if defined(TARGET_X11)
39
40 #if 0
41 Display *display;
42 Window xwindow;
43 #endif
44
45 #if 1
46 Bitmap *objBitmap;
47 Bitmap *botBitmap;
48 Bitmap *sprBitmap;
49 Bitmap *ttlBitmap;
50 #endif
51
52 #if 1
53 Bitmap *screenBitmap;
54 Bitmap *scoreBitmap;
55 #endif
56
57 Pixmap screenPixmap;
58 Pixmap scorePixmap;
59 Pixmap spriteBitmap;
60
61 Pixmap objPixmap;
62 Pixmap objmaskBitmap;
63 Pixmap botPixmap;
64 Pixmap botmaskBitmap;
65 Pixmap sprPixmap;
66 Pixmap sprmaskBitmap;
67 Pixmap ttlPixmap;
68 Pixmap ttlmaskBitmap;
69
70 GC screenGC;
71 GC scoreGC;
72 GC spriteGC;
73 GC antsGC;
74
75 Atom deleteAtom;
76
77 KeySym lastKeySym;
78
79 KeyCode northKeyCode[3];
80 KeyCode eastKeyCode[3];
81 KeyCode southKeyCode[3];
82 KeyCode westKeyCode[3];
83 KeyCode fireKeyCode[3];
84 KeyCode escKeyCode[1];
85
86 char play[SAMPLE_MAX];
87
88 static int sound_pid = -1;
89 int sound_pipe[2] = { -1, -1 }; /* for communication */
90 short *sound_data[SAMPLE_MAX]; /* pointer to sound data */
91 long sound_length[SAMPLE_MAX]; /* length of sound data */
92
93 static Screen *defaultScreen;
94 static Visual *defaultVisual;
95 static Colormap defaultColourmap;
96 static Window defaultRootWindow;
97 static unsigned int screenDepth;
98 static unsigned int screenWidth;
99 static unsigned int screenHeight;
100 static unsigned long screenBlackPixel;
101 static unsigned long screenWhitePixel;
102
103 #if 0
104 static XSizeHints sizeHints;
105 static XSetWindowAttributes setWindowAttributes;
106 static XWMHints wmHints;
107 static XVisualInfo visualInfo;
108 #endif
109 static XGCValues gcValues;
110
111 static Colormap privateColourmap;
112 static Cursor cursor;
113 static XColor *privateColours;
114 static unsigned char *privateFlags;
115 static int privateNumColours;
116
117 static XColor redColour;
118 static XColor whiteColour;
119 static int gotRed;
120 static int gotWhite;
121
122 #if 1
123 static Bitmap *pcxBitmaps[4];
124 static Bitmap *pcxBitmapsX2[4];
125 #endif
126
127 #if 0
128 static Pixmap xpmPixmaps[4];
129 static Pixmap xpmBitmaps[4];
130 static XpmAttributes xpmAttributes[4];
131 static int xpmGot[4];
132 #endif
133
134 static int xpmAllocColourFunc(Display *, Colormap, char *, XColor *, void *);
135 static int xpmFreeColoursFunc(Display *, Colormap, unsigned long *, int, void *);
136
137 static KeyCode keycodes[16];
138
139 #if 0
140 static const char *xpmNames[4] =
141 {
142   "object.xpm",
143   "score.xpm",
144   "sprite.xpm",
145   "title.xpm"
146 };
147 #endif
148
149 #if 1
150 static const char *pcxNames[4] =
151 {
152   "object.pcx",
153   "score.pcx",
154   "sprite.pcx",
155   "title.pcx"
156 };
157 #endif
158
159 static const int xpmCloseness[4] = { 10000, 10000, 40000, 50000 };
160 static const KeySym keysyms[16] =
161 {
162   XK_Up, XK_KP_Up, XK_r, /* north */
163   XK_Right, XK_KP_Right, XK_g, /* east */
164   XK_Down, XK_KP_Down, XK_f, /* south */
165   XK_Left, XK_KP_Left, XK_d, /* west */
166   XK_Shift_L, XK_Control_R, XK_space, /* fire */
167   XK_Escape /* escape */
168 };
169 static const char *sound_names[SAMPLE_MAX] =
170 {
171   "00.blank.au","01.roll.au","02.stone.au","03.nut.au","04.crack.au",
172   "05.bug.au","06.tank.au","07.android.au","08.spring.au","09.slurp.au",
173   "10.eater.au","11.alien.au","12.collect.au","13.diamond.au","14.squash.au",
174   "15.drip.au","16.push.au","17.dirt.au","18.acid.au","19.ball.au",
175   "20.grow.au","21.wonder.au","22.door.au","23.exit.au","24.dynamite.au",
176   "25.tick.au","26.press.au","27.wheel.au","28.boom.au","29.time.au",
177   "30.die.au"
178 };
179 static const int sound_volume[SAMPLE_MAX] =
180 {
181   20,100,100,100,100,20,20,100,100,100,
182   50,100,100,100,100,100,100,100,100,100,
183   100,20,100,100,100,100,100,20,100,100,
184   100
185 };
186
187 #if 0
188 static void xdebug(char *msg)
189 {
190 #if 1
191   XSync(display, False);
192   printf("EM DEBUG: %s\n", msg);
193 #endif
194 }
195 #endif
196
197 int open_all(void)
198 {
199   char name[MAXNAME+2];
200 #if 0
201   void *dummyptr;
202   int dummyint;
203 #endif
204   int i;
205
206 #if 0
207   display = XOpenDisplay(arg_display);
208   if (display == 0)
209   {
210     fprintf(stderr, "%s: \"%s\": %s: %s\n", progname,
211             XDisplayName(arg_display), "failed to open display",
212             strerror(errno));
213     return(1);
214   }
215 #endif
216
217   defaultScreen = DefaultScreenOfDisplay(display);
218   defaultVisual = DefaultVisualOfScreen(defaultScreen);
219   defaultColourmap = DefaultColormapOfScreen(defaultScreen);
220   defaultRootWindow = RootWindowOfScreen(defaultScreen);
221   screenDepth = DefaultDepthOfScreen(defaultScreen);
222   screenWidth = WidthOfScreen(defaultScreen);
223   screenHeight = HeightOfScreen(defaultScreen);
224   screenBlackPixel = BlackPixelOfScreen(defaultScreen);
225   screenWhitePixel = WhitePixelOfScreen(defaultScreen);
226
227 #if 0
228   if (arg_install)
229   {
230     visualInfo.visualid = XVisualIDFromVisual(defaultVisual);
231     dummyptr = XGetVisualInfo(display, VisualIDMask, &visualInfo, &dummyint);
232     if (dummyptr == 0)
233     {
234       fprintf(stderr, "%s: \"%s\": %s: %s\n", progname,
235               XDisplayName(arg_display), "failed to get visual info",
236               strerror(errno));
237       return(1);
238     }
239
240     memcpy(&visualInfo, dummyptr, sizeof(visualInfo));
241     XFree(dummyptr);
242
243     if (visualInfo.class != PseudoColor)
244     {
245       fprintf(stderr, "%s: \"%s\": %s\n", progname, XDisplayName(arg_display),
246               "private colourmap only supported for pseudocolour display");
247       return(1);
248     }
249
250     privateColourmap = XCreateColormap(display, defaultRootWindow,
251                                        defaultVisual, AllocAll);
252     if (privateColourmap == 0)
253     {
254       fprintf(stderr, "%s: \"%s\": %s: %s\n", progname,
255               XDisplayName(arg_display), "failed to create colourmap",
256               strerror(errno));
257       return(1);
258     }
259
260     privateNumColours = visualInfo.colormap_size;
261
262     privateColours = malloc(privateNumColours * sizeof(XColor));
263     if (privateColours == 0)
264     {
265       fprintf(stderr, "%s: %s (%d): %s\n", progname, "malloc failed",
266               privateNumColours * sizeof(XColor), strerror(errno));
267       return(1);
268     }
269
270     for (dummyint = 0; dummyint < privateNumColours; dummyint++)
271       privateColours[dummyint].pixel = dummyint;
272
273     XQueryColors(display, defaultColourmap, privateColours, privateNumColours);
274     XStoreColors(display, privateColourmap, privateColours, privateNumColours);
275
276     privateFlags = malloc(privateNumColours);
277     if (privateFlags == 0)
278     {
279       fprintf(stderr, "%s: %s (%d): %s\n", progname, "malloc failed",
280               privateNumColours, strerror(errno));
281       return(1);
282     }
283
284     memset(privateFlags, 0, privateNumColours);
285
286     /* first two entries (black and white) are already allocated */
287     privateFlags[0] = 1;
288     privateFlags[1] = 1;
289   }
290
291   sizeHints.flags = PSize | PMinSize | PMaxSize;
292   sizeHints.width = 20 * TILEX;
293   sizeHints.height = 12 * TILEY + SCOREY;
294   sizeHints.min_width = sizeHints.max_width = sizeHints.width;
295   sizeHints.min_height = sizeHints.max_height = sizeHints.height;
296
297   if (arg_geometry)
298   {
299     dummyint = XWMGeometry(display, XScreenNumberOfScreen(defaultScreen),
300                            arg_geometry, 0, 2, &sizeHints, &sizeHints.x,
301                            &sizeHints.y, &dummyint, &dummyint,
302                            &sizeHints.win_gravity);
303     if (dummyint & (XValue | YValue))
304       sizeHints.flags |= USPosition | PWinGravity;
305   }
306
307   xwindow = XCreateWindow(display, defaultRootWindow, sizeHints.x, sizeHints.y,
308                           sizeHints.width, sizeHints.height, 2, screenDepth,
309                           InputOutput, CopyFromParent, 0, 0);
310   if (xwindow == 0)
311   {
312     fprintf(stderr, "%s: \"%s\": %s: %s\n", progname,
313             XDisplayName(arg_display), "failed to open window",
314             strerror(errno));
315     return(1);
316   }
317
318   setWindowAttributes.background_pixel = screenBlackPixel;
319   setWindowAttributes.border_pixel = screenWhitePixel;
320   setWindowAttributes.backing_store = NotUseful;
321   setWindowAttributes.override_redirect = False;
322   setWindowAttributes.event_mask =
323     KeyPressMask | EnterWindowMask | LeaveWindowMask | ExposureMask;
324   setWindowAttributes.colormap =
325     privateColourmap ? privateColourmap : defaultColourmap;
326   XChangeWindowAttributes(display, xwindow,
327                           CWBackPixel | CWBorderPixel | CWBackingStore |
328                           CWOverrideRedirect | CWEventMask | CWColormap,
329                           &setWindowAttributes);
330
331   XStoreName(display, xwindow, "Emerald Mine");
332
333   wmHints.flags = InputHint | StateHint;
334   wmHints.input = True;
335   wmHints.initial_state = NormalState;
336   XSetWMHints(display, xwindow, &wmHints);
337
338   XSetWMNormalHints(display, xwindow, &sizeHints);
339
340   deleteAtom = XInternAtom(display, "WM_DELETE_WINDOW", False);
341   XSetWMProtocols(display, xwindow, &deleteAtom, 1);
342
343   cursor = XCreateFontCursor(display, XC_trek);
344   if (cursor) XDefineCursor(display, xwindow, cursor);
345
346   XMapWindow(display, xwindow);
347 #endif
348
349 #if 0
350   for (i = 0; i < 4; i++)
351   {
352     name[MAXNAME] = 0;
353     if (arg_basedir)
354     {
355       snprintf(name, MAXNAME+2, "%s/%s/%s", arg_basedir, EM_GFX_DIR,
356                xpmNames[i]);
357     }
358     else
359     {
360       snprintf(name, MAXNAME+2, "%s/%s", EM_GFX_DIR, xpmNames[i]);
361     }
362
363     if (name[MAXNAME]) snprintf_overflow("read graphics/ files");
364
365     xpmAttributes[i].valuemask =
366       XpmColormap | XpmReturnAllocPixels | XpmExactColors | XpmCloseness |
367       XpmAllocColor | XpmFreeColors;
368     xpmAttributes[i].colormap =
369       privateColourmap ? privateColourmap : defaultColourmap;
370     xpmAttributes[i].exactColors = False;
371     xpmAttributes[i].closeness = xpmCloseness[i];
372     xpmAttributes[i].alloc_color = xpmAllocColourFunc;
373     xpmAttributes[i].free_colors = xpmFreeColoursFunc;
374     dummyint = XpmReadFileToPixmap(display, xwindow, name, &xpmPixmaps[i],
375                                    &xpmBitmaps[i], &xpmAttributes[i]);
376     if (dummyint)
377     {
378       fprintf(stderr, "%s: \"%s\": \"%s\": %s: %s: %s\n", progname,
379               XDisplayName(arg_display), name, "failed to read xpm",
380               XpmGetErrorString(dummyint), strerror(errno));
381       return(1);
382     }
383
384     xpmGot[i] = 1;
385   }
386 #endif
387
388   for (i = 0; i < 4; i++)
389   {
390     name[MAXNAME] = 0;
391     snprintf(name, MAXNAME+2, "%s/%s", EM_GFX_DIR, pcxNames[i]);
392
393     if (name[MAXNAME])
394       snprintf_overflow("read graphics/ files");
395
396     if ((pcxBitmaps[i] = LoadImage(name)) == NULL)
397     {
398       printf("::: LoadImage() failed for file '%s'\n", name);
399       return 1;
400     }
401   }
402
403   objBitmap = pcxBitmaps[0];
404   botBitmap = pcxBitmaps[1];
405   sprBitmap = pcxBitmaps[2];
406   ttlBitmap = pcxBitmaps[3];
407
408 #if 0
409   objPixmap = xpmPixmaps[0];
410   botPixmap = xpmPixmaps[1];
411   sprPixmap = xpmPixmaps[2];
412   ttlPixmap = xpmPixmaps[3];
413   objmaskBitmap = xpmBitmaps[0];
414   botmaskBitmap = xpmBitmaps[1];
415   sprmaskBitmap = xpmBitmaps[2];
416   ttlmaskBitmap = xpmBitmaps[3];
417 #else
418   objPixmap = pcxBitmaps[0]->drawable;
419   botPixmap = pcxBitmaps[1]->drawable;
420   sprPixmap = pcxBitmaps[2]->drawable;
421   ttlPixmap = pcxBitmaps[3]->drawable;
422   objmaskBitmap = pcxBitmaps[0]->clip_mask;
423   botmaskBitmap = pcxBitmaps[1]->clip_mask;
424   sprmaskBitmap = pcxBitmaps[2]->clip_mask;
425   ttlmaskBitmap = pcxBitmaps[3]->clip_mask;
426 #endif
427
428 #if 1
429   for (i = 0; i < 4; i++)
430   {
431     Pixmap clip_mask;
432
433     if ((clip_mask = XCreatePixmap(display, window->drawable,
434                                    pcxBitmaps[i]->width * 2,
435                                    pcxBitmaps[i]->height * 2, 1))
436         == None)
437     {
438       printf("::: cannot create clip mask");
439       return 1;
440     }
441
442 #if 0
443     {
444       XGCValues clip_gc_values;
445       unsigned long clip_gc_valuemask;
446       GC gc;
447
448       clip_gc_values.graphics_exposures = False;
449       clip_gc_valuemask = GCGraphicsExposures;
450       if ((gc = XCreateGC(display, clip_mask,
451                           clip_gc_valuemask, &clip_gc_values)) == None)
452       {
453         printf("X       CreateGC failed\n");
454         exit(1);
455       }
456
457       XFillRectangle(display, clip_mask, gc, 0, 0,
458                      pcxBitmaps[i]->width * 2,
459                      pcxBitmaps[i]->height * 2);
460     }
461 #endif
462
463 #if 0
464     {
465       byte * src_ptr;
466       int src_width = pcxBitmaps[i]->width;
467       int src_height = pcxBitmaps[i]->height;
468
469 #if 0
470       printf("::: %d, %d [%ld -> %ld (%ld)]\n",
471              src_width, src_height,
472              src_ptr,
473              src_ptr + src_width * src_height * 1,
474              src_width * src_height * 1);
475 #endif
476
477 #if 0
478       for (i = src_ptr; i < src_ptr + src_width * src_height * 1; i++)
479       {
480         byte x = *(byte *)i;
481
482         x = x * 1;
483       }
484 #endif
485     }
486 #endif
487
488     if (ZOOM_FACTOR > 1)
489       pcxBitmapsX2[i] = ZoomBitmap(pcxBitmaps[i],
490                                    pcxBitmaps[i]->width  * ZOOM_FACTOR,
491                                    pcxBitmaps[i]->height * ZOOM_FACTOR);
492     else
493       pcxBitmapsX2[i] = pcxBitmaps[i];
494
495 #if 1
496
497 #if 0
498     printf("::: CREATING NEW CLIPMASKS ...\n");
499 #endif
500 #if 1
501     clip_mask = Pixmap_to_Mask(pcxBitmapsX2[i]->drawable,
502                                pcxBitmapsX2[i]->width,
503                                pcxBitmapsX2[i]->height);
504 #endif
505 #if 0
506     printf("::: CREATING NEW CLIPMASKS DONE\n");
507 #endif
508
509     pcxBitmapsX2[i]->clip_mask = clip_mask;
510
511     /* add clip mask GC */
512     {
513       XGCValues clip_gc_values;
514       unsigned long clip_gc_valuemask;
515
516       clip_gc_values.graphics_exposures = False;
517       clip_gc_values.clip_mask = pcxBitmapsX2[i]->clip_mask;
518       clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
519       pcxBitmapsX2[i]->stored_clip_gc = XCreateGC(display,
520                                                   window->drawable,
521                                                   clip_gc_valuemask,
522                                                   &clip_gc_values);
523     }
524
525 #if 0
526     printf("::: %ld, %ld, %ld, %ld, %ld, %ld, %ld\n",
527            pcxBitmaps[i]->gc,
528            pcxBitmaps[i]->clip_mask, pcxBitmapsX2[i]->clip_mask,
529            pcxBitmaps[i]->width, pcxBitmaps[i]->height,
530            pcxBitmapsX2[i]->width, pcxBitmapsX2[i]->height);
531 #endif
532
533 #if 0
534     ZoomPixmap(display, pcxBitmaps[i]->gc,
535                pcxBitmaps[i]->clip_mask, pcxBitmapsX2[i]->clip_mask,
536                pcxBitmaps[i]->width, pcxBitmaps[i]->height,
537                pcxBitmapsX2[i]->width, pcxBitmapsX2[i]->height);
538 #endif
539
540 #endif
541   }
542
543   objBitmap = pcxBitmapsX2[0];
544   botBitmap = pcxBitmapsX2[1];
545   sprBitmap = pcxBitmapsX2[2];
546   ttlBitmap = pcxBitmapsX2[3];
547
548   objPixmap = pcxBitmapsX2[0]->drawable;
549   botPixmap = pcxBitmapsX2[1]->drawable;
550   sprPixmap = pcxBitmapsX2[2]->drawable;
551   ttlPixmap = pcxBitmapsX2[3]->drawable;
552 #if 1
553   objmaskBitmap = pcxBitmapsX2[0]->clip_mask;
554   botmaskBitmap = pcxBitmapsX2[1]->clip_mask;
555   sprmaskBitmap = pcxBitmapsX2[2]->clip_mask;
556   ttlmaskBitmap = pcxBitmapsX2[3]->clip_mask;
557 #endif
558 #endif
559
560 #if 1
561   screenBitmap = CreateBitmap(MAX_BUF_XSIZE * TILEX, MAX_BUF_YSIZE * TILEY,
562                               DEFAULT_DEPTH);
563   scoreBitmap = CreateBitmap(20 * TILEX, SCOREY, DEFAULT_DEPTH);
564 #endif
565
566   screenPixmap = XCreatePixmap(display, xwindow,
567                                MAX_BUF_XSIZE * TILEX, MAX_BUF_YSIZE * TILEY,
568                                screenDepth);
569   if (screenPixmap == 0)
570   {
571     fprintf(stderr, "%s: \"%s\": %s: %s\n", progname,
572             XDisplayName(arg_display), "failed to create pixmap",
573             strerror(errno));
574     return(1);
575   }
576
577   scorePixmap = XCreatePixmap(display, xwindow, 20 * TILEX, SCOREY,
578                               screenDepth);
579   if (scorePixmap == 0)
580   {
581     fprintf(stderr, "%s: \"%s\": %s: %s\n", progname,
582             XDisplayName(arg_display), "failed to create pixmap",
583             strerror(errno));
584     return(1);
585   }
586
587 #if 1
588   screenBitmap->drawable = screenPixmap;
589   scoreBitmap->drawable = scorePixmap;
590 #endif
591
592   spriteBitmap = XCreatePixmap(display, xwindow, TILEX, TILEY, 1);
593   if (spriteBitmap == 0)
594   {
595     fprintf(stderr, "%s: \"%s\": %s: %s\n", progname,
596             XDisplayName(arg_display), "failed to create pixmap",
597             strerror(errno));
598     return(1);
599   }
600
601   redColour.pixel = screenWhitePixel;
602   whiteColour.pixel = screenBlackPixel;
603   gotRed = (xpmAllocColourFunc(display, privateColourmap ? privateColourmap :
604                                defaultColourmap,
605                                "red", &redColour, 0) > 0);
606   gotWhite = (xpmAllocColourFunc(display, privateColourmap ? privateColourmap :
607                                  defaultColourmap,
608                                  "white", &whiteColour, 0) > 0);
609
610   gcValues.graphics_exposures = False;
611   screenGC = XCreateGC(display, screenPixmap, GCGraphicsExposures, &gcValues);
612   if (screenGC == 0)
613   {
614     fprintf(stderr, "%s: \"%s\": %s: %s\n", progname,
615             XDisplayName(arg_display), "failed to create graphics context",
616             strerror(errno));
617     return(1);
618   }
619
620   gcValues.graphics_exposures = False;
621   scoreGC = XCreateGC(display, scorePixmap, GCGraphicsExposures, &gcValues);
622   if (scoreGC == 0)
623   {
624     fprintf(stderr, "%s: \"%s\": %s: %s\n", progname,
625             XDisplayName(arg_display), "failed to create graphics context",
626             strerror(errno));
627     return(1);
628   }
629
630   gcValues.function =
631     objmaskBitmap ? GXcopyInverted : sprmaskBitmap ? GXcopy : GXset;
632   gcValues.graphics_exposures = False;
633   spriteGC = XCreateGC(display, spriteBitmap, GCFunction | GCGraphicsExposures,
634                        &gcValues);
635   if (spriteGC == 0)
636   {
637     fprintf(stderr, "%s: \"%s\": %s: %s\n", progname,
638             XDisplayName(arg_display), "failed to create graphics context",
639             strerror(errno));
640     return(1);
641   }
642
643   gcValues.foreground = redColour.pixel;
644   gcValues.background = whiteColour.pixel;
645   gcValues.line_style = LineDoubleDash;
646   gcValues.graphics_exposures = False;
647   antsGC = XCreateGC(display, screenPixmap,
648                      GCForeground | GCBackground | GCLineStyle |
649                      GCGraphicsExposures,
650                      &gcValues);
651   if (antsGC == 0)
652   {
653     fprintf(stderr, "%s: \"%s\": %s: %s\n", progname,
654             XDisplayName(arg_display), "failed to create graphics context",
655             strerror(errno));
656     return(1);
657   }
658
659   for (i = 0; i < 16; i++)
660     keycodes[i] = XKeysymToKeycode(display, keysyms[i]);
661
662   for (i = 0; i < 3; i++)
663     northKeyCode[i] = keycodes[i + 0];
664   for (i = 0; i < 3; i++)
665     eastKeyCode[i] = keycodes[i + 3];
666   for (i = 0; i < 3; i++)
667     southKeyCode[i] = keycodes[i + 6];
668   for (i = 0; i < 3; i++)
669     westKeyCode[i] = keycodes[i + 9];
670   for (i = 0; i < 3; i++)
671     fireKeyCode[i] = keycodes[i + 12];
672   for (i = 0; i < 1; i++)
673     escKeyCode[i] = keycodes[i + 15];
674
675   /* ----------------------------------------------------------------- */
676
677 #if 0
678   {
679     Bitmap *bm = pcxBitmaps[2];
680     Pixmap clip_mask = bm->clip_mask;
681
682     if (clip_mask)
683     {
684 #if 1
685       int width = bm->width;
686       int height = bm->height;
687 #else
688       int width = 16 * 4;
689       int height = 16 * 4;
690 #endif
691       XImage *src_ximage = XGetImage(display, clip_mask, 0, 0,
692                                      width, height, AllPlanes, ZPixmap);
693       XImage *dst_ximage = XGetImage(display, xwindow, 0, 0,
694                                      width, height, AllPlanes, ZPixmap);
695       int x, y;
696
697       if (src_ximage == NULL)
698       {
699         printf("src_ximage failed\n");
700         exit(1);
701       }
702
703       if (dst_ximage == NULL)
704       {
705         printf("dst_ximage failed\n");
706         exit(1);
707       }
708
709       printf("::: DISPLAY CLIP MASK ...\n");
710
711       for (x=0; x<width; x++)
712       {
713         for (y=0; y<height; y++)
714         {
715           unsigned long pixel = XGetPixel(src_ximage, x, y);
716
717           if (pixel != BlackPixel(display, screen))
718             pixel = WhitePixel(display, screen);
719
720           XPutPixel(dst_ximage, x, y, pixel);
721         }
722       }
723
724       printf("::: DISPLAY CLIP MASK NOW\n");
725
726       XPutImage(display, xwindow, screenGC, dst_ximage, 0, 0,
727                 0, 13 * TILEY, width, height);
728
729       printf("::: DISPLAY CLIP MASK DONE\n");
730     }
731   }
732 #endif
733
734   /* ----------------------------------------------------------------- */
735
736 #if 0
737   {
738     int ii = 2;
739
740     XGCValues clip_gc_values;
741     unsigned long clip_gc_valuemask;
742
743 #if 1
744     GC gc = screenGC;
745 #else
746 #if 1
747     GC gc = pcxBitmaps[ii]->stored_clip_gc;
748 #else
749     GC gc = pcxBitmaps[ii]->gc;
750 #endif
751 #endif
752     Pixmap src_pixmap = pcxBitmaps[ii]->clip_mask;
753     Pixmap dst_pixmap = pcxBitmapsX2[ii]->clip_mask;
754     int src_width = pcxBitmaps[ii]->width;
755     int src_height = pcxBitmaps[ii]->height;
756     int dst_width = pcxBitmapsX2[ii]->width;
757     int dst_height = pcxBitmapsX2[ii]->height;
758
759     XImage *src_ximage, *dst_ximage;
760     byte *src_ptr, *dst_ptr;
761     int bits_per_pixel;
762     int bytes_per_pixel;
763     int x, y, xx, yy, i;
764 #if 1
765     boolean scale_down = (src_width > dst_width);
766     int zoom_factor;
767 #else
768     int zoom_factor = src_width / dst_width;    /* currently very limited! */
769 #endif
770     int row_skip, col_skip;
771
772     printf("::: %d\n", scale_down);
773
774     xdebug("::: ZOOM STEP 1");
775
776     clip_gc_values.graphics_exposures = False;
777     clip_gc_valuemask = GCGraphicsExposures;
778     if ((gc = XCreateGC(display, pcxBitmaps[ii]->clip_mask,
779                         clip_gc_valuemask, &clip_gc_values)) == None)
780     {
781       printf("XCreateGC failed\n");
782       exit(1);
783     }
784
785     xdebug("::: ZOOM STEP 2");
786
787     if (scale_down)
788     {
789       zoom_factor = src_width / dst_width;
790
791       /* adjust source image size to integer multiple of destination size */
792       src_width  = dst_width  * zoom_factor;
793       src_height = dst_height * zoom_factor;
794     }
795     else
796     {
797       zoom_factor = dst_width / src_width;
798
799       /* no adjustment needed when scaling up (some pixels may be left blank) */
800     }
801
802     /* copy source pixmap to temporary image */
803     if ((src_ximage = XGetImage(display, src_pixmap, 0, 0, src_width, src_height,
804                                 AllPlanes, ZPixmap)) == NULL)
805       Error(ERR_EXIT, "ZoomPixmap(): XGetImage() failed");
806
807     bits_per_pixel = src_ximage->bits_per_pixel;
808     bytes_per_pixel = (bits_per_pixel + 7) / 8;
809
810     printf("::: bits_per_pixel == %d\n", bits_per_pixel);
811
812     if ((dst_ximage = XCreateImage(display, visual, src_ximage->depth, ZPixmap,
813                                    0, NULL, dst_width, dst_height,
814                                    8, dst_width * bytes_per_pixel)) == NULL)
815       Error(ERR_EXIT, "ZoomPixmap(): XC reateImage() failed");
816
817     dst_ximage->data =
818       checked_malloc(dst_width * dst_height * bytes_per_pixel);
819     dst_ximage->byte_order = src_ximage->byte_order;
820
821     src_ptr = (byte *)src_ximage->data;
822     dst_ptr = (byte *)dst_ximage->data;
823
824     if (scale_down)
825     {
826       col_skip = (zoom_factor - 1) * bytes_per_pixel;
827       row_skip = col_skip * src_width;
828
829       /* scale image down by scaling factor 'zoom_factor' */
830       for (y = 0; y < src_height; y += zoom_factor, src_ptr += row_skip)
831         for (x = 0; x < src_width; x += zoom_factor, src_ptr += col_skip)
832           for (i = 0; i < bytes_per_pixel; i++)
833             *dst_ptr++ = *src_ptr++;
834     }
835     else
836     {
837       row_skip = src_width * bytes_per_pixel;
838
839 #if 1
840       printf("::: %d, %d -> %d, %d [%d / %d]\n[%ld -> %ld (%ld)] [%ld -> %ld (%ld)]\n",
841              src_width, src_height,
842              dst_width, dst_height,
843              zoom_factor, bytes_per_pixel,
844              src_ptr,
845              src_ptr + src_width * src_height * bytes_per_pixel,
846              src_width * src_height * bytes_per_pixel,
847              dst_ptr,
848              dst_ptr + dst_width * dst_height * bytes_per_pixel,
849              dst_width * dst_height * bytes_per_pixel);
850 #endif
851
852 #if 0
853       printf("A\n");
854
855       for (i = 0; i < src_width * src_height * bytes_per_pixel;
856            i++)
857       {
858         byte x = *(byte *)(src_ptr + i);
859
860         printf("::: %d ...\n", i);
861
862         x = x * 1;
863       }
864
865       printf("B\n");
866 #endif
867
868       /* scale image up by scaling factor 'zoom_factor' */
869       for (y = 0; y < src_height; y++)
870       {
871         for (yy = 0; yy < zoom_factor; yy++)
872         {
873           if (yy > 0)
874             src_ptr -= row_skip;
875
876 #if 0
877           printf("::: [%d -> %ld / %ld]\n", y, src_ptr, dst_ptr);
878 #endif
879
880           for (x = 0; x < src_width; x++)
881           {
882             for (xx = 0; xx < zoom_factor; xx++)
883               for (i = 0; i < bytes_per_pixel; i++)
884 #if 1
885               {
886 #if 0
887                 printf("::: %d\n", *(src_ptr + i));
888 #endif
889
890                 *dst_ptr++ = *(src_ptr + i);
891               }
892 #else
893             *dst_ptr++ = 0;
894 #endif
895
896             src_ptr += i;
897           }
898         }
899       }
900     }
901
902     xdebug("::: ZOOM STEP 9");
903
904     /* copy scaled image to destination pixmap */
905     XPutImage(display, dst_pixmap, gc, dst_ximage, 0, 0, 0, 0,
906               dst_width, dst_height);
907
908     /* free temporary images */
909     X11DestroyImage(src_ximage);
910     X11DestroyImage(dst_ximage);
911
912
913     xdebug("::: ZOOM DONE");
914
915   }
916 #endif
917
918   /* ----------------------------------------------------------------- */
919
920 #if 0
921   {
922     Bitmap *bm = pcxBitmapsX2[2];
923     Pixmap clip_mask = bm->clip_mask;
924
925     if (clip_mask)
926     {
927 #if 0
928       int width = bm->width;
929       int height = bm->height;
930 #else
931       int width = 16 * 4;
932       int height = 16 * 4;
933 #endif
934       XImage *src_ximage = XGetImage(display, clip_mask, 0, 0,
935                                      width, height, AllPlanes, ZPixmap);
936       XImage *dst_ximage = XGetImage(display, xwindow, 0, 0,
937                                      width, height, AllPlanes, ZPixmap);
938       int x, y;
939
940       if (src_ximage == NULL)
941       {
942         printf("src_ximage failed\n");
943         exit(1);
944       }
945
946       if (dst_ximage == NULL)
947       {
948         printf("dst_ximage failed\n");
949         exit(1);
950       }
951
952       printf("::: DISPLAY CLIP MASK ...\n");
953
954       for (x=0; x<width; x++)
955       {
956         for (y=0; y<height; y++)
957         {
958           unsigned long pixel = XGetPixel(src_ximage, x, y);
959
960           if (pixel != BlackPixel(display, screen))
961             pixel = WhitePixel(display, screen);
962
963           XPutPixel(dst_ximage, x, y, pixel);
964         }
965       }
966
967       printf("::: DISPLAY CLIP MASK NOW\n");
968
969       XPutImage(display, xwindow, screenGC, dst_ximage, 0, 0,
970                 0, 13 * TILEY + height, width, height);
971
972       printf("::: DISPLAY CLIP MASK DONE\n");
973     }
974   }
975 #endif
976
977   /* ----------------------------------------------------------------- */
978
979 #if 0
980   {
981     XImage *dst_ximage;
982
983     printf("::: GET IMAGE ...\n");
984
985     dst_ximage = XGetImage(display, xwindow, 0, 0,
986                            16, 16, AllPlanes, ZPixmap);
987     if (dst_ximage == NULL)
988     {
989       printf("dst_ximage failed\n");
990       exit(1);
991     }
992
993     printf("::: PUT IMAGE ...\n");
994
995     XPutImage(display, xwindow, screenGC, dst_ximage, 0, 0,
996               0, 13 * TILEY, 10, 10);
997
998     printf("::: PUT IMAGE DONE\n");
999   }
1000 #endif
1001
1002   /* ----------------------------------------------------------------- */
1003
1004 #if defined(PLATFORM_LINUX) || defined(PLATFORM_BSD)
1005   if (arg_silence == 0)
1006   {
1007     for (i = 0; i < SAMPLE_MAX; i++)
1008     {
1009       name[MAXNAME] = 0;
1010
1011       if (arg_basedir)
1012       {
1013         snprintf(name, MAXNAME+2, "%s/%s/%s", arg_basedir, EM_SND_DIR,
1014                  sound_names[i]);
1015       }
1016       else
1017       {
1018         snprintf(name, MAXNAME+2, "%s/%s", EM_SND_DIR, sound_names[i]);
1019       }
1020
1021       if (name[MAXNAME]) snprintf_overflow("read sounds/ directory");
1022
1023       if (read_sample(name, &sound_data[i], &sound_length[i]))
1024         return(1);
1025
1026       {
1027         short *ptr, *stop;
1028         int mult = sound_volume[i] * 65536 / (100 * MIXER_MAX);
1029         stop = sound_data[i] + sound_length[i];
1030         for (ptr = sound_data[i]; ptr < stop; ptr++)
1031           *ptr = (*ptr * mult) / 65536;
1032       }
1033     }
1034
1035     if (pipe(sound_pipe) == -1)
1036     {
1037       fprintf(stderr, "%s: %s: %s\n", progname, "unable to create sound pipe",
1038               strerror(errno));
1039       return(1);
1040     }
1041
1042     sound_pid = fork();
1043     if (sound_pid == -1)
1044     {
1045       fprintf(stderr, "%s: %s: %s\n", progname, "unable to fork sound thread",
1046               strerror(errno));
1047       return(1);
1048     }
1049
1050     close(sound_pipe[sound_pid == 0]); sound_pipe[sound_pid == 0] = -1;
1051     if (sound_pid == 0)
1052       _exit(sound_thread());
1053
1054     signal(SIGPIPE, SIG_IGN); /* dont crash if sound process dies */
1055   }
1056
1057 #endif /* defined(PLATFORM_LINUX) || defined(PLATFORM_BSD) */
1058
1059   return(0);
1060 }
1061
1062 void close_all(void)
1063 {
1064   int i;
1065
1066   if (sound_pid != -1)
1067   {
1068     kill(sound_pid, SIGTERM);
1069     waitpid(sound_pid, 0, 0);
1070   }
1071
1072   if (sound_pipe[0] != -1)
1073     close(sound_pipe[0]);
1074   if (sound_pipe[1] != -1)
1075     close(sound_pipe[1]);
1076
1077   for (i = 0; i < SAMPLE_MAX; i++)
1078     if (sound_data[i])
1079       free(sound_data[i]);
1080
1081 #if 0
1082   for (i = 0; i < 4; i++)
1083     if (xpmPixmaps[i])
1084       XFreePixmap(display, xpmPixmaps[i]);
1085   for (i = 0; i < 4; i++)
1086     if (xpmBitmaps[i])
1087       XFreePixmap(display, xpmBitmaps[i]);
1088   for (i = 0; i < 4; i++)
1089     if (xpmGot[i])
1090     {
1091       xpmFreeColoursFunc(display, xpmAttributes[i].colormap,
1092                          xpmAttributes[i].alloc_pixels,
1093                          xpmAttributes[i].nalloc_pixels, 0);
1094       XpmFreeAttributes(&xpmAttributes[i]);
1095     }
1096 #endif
1097
1098   if (gotRed)
1099     xpmFreeColoursFunc(display,
1100                        privateColourmap ? privateColourmap : defaultColourmap,
1101                        &redColour.pixel, 1, 0);
1102   if (gotWhite)
1103     xpmFreeColoursFunc(display,
1104                        privateColourmap ? privateColourmap : defaultColourmap,
1105                        &whiteColour.pixel, 1, 0);
1106
1107   if (screenGC)
1108     XFreeGC(display, screenGC);
1109   if (scoreGC)
1110     XFreeGC(display, scoreGC);
1111   if (spriteGC)
1112     XFreeGC(display, spriteGC);
1113   if (antsGC)
1114     XFreeGC(display, antsGC);
1115   if (screenPixmap)
1116     XFreePixmap(display, screenPixmap);
1117   if (scorePixmap)
1118     XFreePixmap(display, scorePixmap);
1119   if (spriteBitmap)
1120     XFreePixmap(display, spriteBitmap);
1121   if (xwindow)
1122     XDestroyWindow(display, xwindow);
1123   if (cursor)
1124     XFreeCursor(display, cursor);
1125   if (privateColourmap)
1126     XFreeColormap(display, privateColourmap);
1127   if (privateColours)
1128     free(privateColours);
1129   if (privateFlags)
1130     free(privateFlags);
1131 #if 0
1132   if (display)
1133     XCloseDisplay(display);
1134 #endif
1135 }
1136
1137 /* ---------------------------------------------------------------------- */
1138
1139 void sound_play(void)
1140 {
1141   if (sound_pipe[1] != -1)
1142   {
1143     if (write(sound_pipe[1], &play, sizeof(play)) == -1)
1144     {
1145       fprintf(stderr, "%s: %s: %s\n", progname, "write sound",
1146               strerror(errno));
1147
1148       if (sound_pipe[0] != -1)
1149       {
1150         close(sound_pipe[0]);
1151         sound_pipe[0] = -1;
1152       }
1153
1154       if (sound_pipe[1] != -1)
1155       {
1156         close(sound_pipe[1]);
1157         sound_pipe[1] = -1;
1158       }
1159     }
1160   }
1161
1162   memset(play, 0, sizeof(play));
1163 }
1164
1165 /* ---------------------------------------------------------------------- */
1166
1167 static int xpmAllocColourFunc(Display *display, Colormap colourmap,
1168                               char *colourname, XColor *xcolour, void *closure)
1169 {
1170   int i, match;
1171   int r,g,b;
1172   long best, sum;
1173
1174   if (colourname)
1175     if (XParseColor(display, colourmap, colourname, xcolour) == 0)
1176       return(-1); /* invalid name */
1177   if (colourmap != privateColourmap)
1178     return(XAllocColor(display, colourmap, xcolour) != 0);
1179
1180   /* first try to find an exact match */
1181   match = -1;
1182   for (i = 0; i < privateNumColours; i++)
1183   {
1184     if (privateColours[i].red == xcolour->red &&
1185         privateColours[i].green == xcolour->green &&
1186         privateColours[i].blue == xcolour->blue)
1187       match = i;
1188   }
1189
1190   if (match != -1)
1191   {
1192     privateFlags[match] = 1;
1193     xcolour->pixel = privateColours[match].pixel;
1194     return(1);
1195   }
1196
1197   /* then find an unallocated colour that is close to what we want */
1198   match = -1;
1199   best = 1000000;
1200   for (i = 0; i < privateNumColours; i++)
1201   {
1202     if (privateFlags[i])
1203       continue; /* skip if it is already allocated */
1204
1205     r = (privateColours[i].red - xcolour->red) / 256;
1206     g = (privateColours[i].green - xcolour->green) / 256;
1207     b = (privateColours[i].blue - xcolour->blue) / 256;
1208     sum = r * r + g * g + b * b;
1209
1210     if (sum < best)
1211     {
1212       best = sum;
1213       match = i;
1214     }
1215   }
1216
1217   if (match != -1)
1218   {
1219     privateFlags[match] = 1;
1220     privateColours[match].red = xcolour->red;
1221     privateColours[match].green = xcolour->green;
1222     privateColours[match].blue = xcolour->blue;
1223     XStoreColor(display, colourmap, &privateColours[match]);
1224     xcolour->pixel = privateColours[match].pixel;
1225     return(1); /* found a close match */
1226   }
1227
1228   /* if all else fails, just find the closest colour and return it */
1229   match = -1;
1230   best = 1000000;
1231   for (i = 0; i < privateNumColours; i++)
1232   {
1233     r = (privateColours[i].red - xcolour->red) / 256;
1234     g = (privateColours[i].green - xcolour->green) / 256;
1235     b = (privateColours[i].blue - xcolour->blue) / 256;
1236     sum = r * r + g * g + b * b;
1237
1238     if (sum < best)
1239     {
1240       best = sum;
1241       match = i;
1242     }
1243   }
1244
1245   if (match != -1)
1246   {
1247     xcolour->red = privateColours[match].red;
1248     xcolour->green = privateColours[match].green;
1249     xcolour->blue = privateColours[match].blue;
1250     xcolour->pixel = privateColours[match].pixel;
1251     return(1); /* best we could do */
1252   }
1253
1254   return(0); /* still didnt find one, give up */
1255 }
1256
1257 static int xpmFreeColoursFunc(Display *display, Colormap colourmap,
1258                               unsigned long *pixels, int npixels,
1259                               void *closure)
1260 {
1261   if (colourmap != privateColourmap)
1262     XFreeColors(display, colourmap, pixels, npixels, 0);
1263
1264   return(1); /* non-zero for success */
1265 }
1266
1267 #endif