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