64d734ccb382fce18131199b986a9764982d3838
[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(22 * TILEX, 14 * TILEY, DEFAULT_DEPTH);
562   scoreBitmap = CreateBitmap(20 * TILEX, SCOREY, DEFAULT_DEPTH);
563 #endif
564
565   screenPixmap = XCreatePixmap(display, xwindow, 22 * TILEX, 14 * TILEY,
566                                screenDepth);
567   if (screenPixmap == 0)
568   {
569     fprintf(stderr, "%s: \"%s\": %s: %s\n", progname,
570             XDisplayName(arg_display), "failed to create pixmap",
571             strerror(errno));
572     return(1);
573   }
574
575   scorePixmap = XCreatePixmap(display, xwindow, 20 * TILEX, SCOREY,
576                               screenDepth);
577   if (scorePixmap == 0)
578   {
579     fprintf(stderr, "%s: \"%s\": %s: %s\n", progname,
580             XDisplayName(arg_display), "failed to create pixmap",
581             strerror(errno));
582     return(1);
583   }
584
585 #if 1
586   screenBitmap->drawable = screenPixmap;
587   scoreBitmap->drawable = scorePixmap;
588 #endif
589
590   spriteBitmap = XCreatePixmap(display, xwindow, TILEX, TILEY, 1);
591   if (spriteBitmap == 0)
592   {
593     fprintf(stderr, "%s: \"%s\": %s: %s\n", progname,
594             XDisplayName(arg_display), "failed to create pixmap",
595             strerror(errno));
596     return(1);
597   }
598
599   redColour.pixel = screenWhitePixel;
600   whiteColour.pixel = screenBlackPixel;
601   gotRed = (xpmAllocColourFunc(display, privateColourmap ? privateColourmap :
602                                defaultColourmap,
603                                "red", &redColour, 0) > 0);
604   gotWhite = (xpmAllocColourFunc(display, privateColourmap ? privateColourmap :
605                                  defaultColourmap,
606                                  "white", &whiteColour, 0) > 0);
607
608   gcValues.graphics_exposures = False;
609   screenGC = XCreateGC(display, screenPixmap, GCGraphicsExposures, &gcValues);
610   if (screenGC == 0)
611   {
612     fprintf(stderr, "%s: \"%s\": %s: %s\n", progname,
613             XDisplayName(arg_display), "failed to create graphics context",
614             strerror(errno));
615     return(1);
616   }
617
618   gcValues.graphics_exposures = False;
619   scoreGC = XCreateGC(display, scorePixmap, GCGraphicsExposures, &gcValues);
620   if (scoreGC == 0)
621   {
622     fprintf(stderr, "%s: \"%s\": %s: %s\n", progname,
623             XDisplayName(arg_display), "failed to create graphics context",
624             strerror(errno));
625     return(1);
626   }
627
628   gcValues.function =
629     objmaskBitmap ? GXcopyInverted : sprmaskBitmap ? GXcopy : GXset;
630   gcValues.graphics_exposures = False;
631   spriteGC = XCreateGC(display, spriteBitmap, GCFunction | GCGraphicsExposures,
632                        &gcValues);
633   if (spriteGC == 0)
634   {
635     fprintf(stderr, "%s: \"%s\": %s: %s\n", progname,
636             XDisplayName(arg_display), "failed to create graphics context",
637             strerror(errno));
638     return(1);
639   }
640
641   gcValues.foreground = redColour.pixel;
642   gcValues.background = whiteColour.pixel;
643   gcValues.line_style = LineDoubleDash;
644   gcValues.graphics_exposures = False;
645   antsGC = XCreateGC(display, screenPixmap,
646                      GCForeground | GCBackground | GCLineStyle |
647                      GCGraphicsExposures,
648                      &gcValues);
649   if (antsGC == 0)
650   {
651     fprintf(stderr, "%s: \"%s\": %s: %s\n", progname,
652             XDisplayName(arg_display), "failed to create graphics context",
653             strerror(errno));
654     return(1);
655   }
656
657   for (i = 0; i < 16; i++)
658     keycodes[i] = XKeysymToKeycode(display, keysyms[i]);
659
660   for (i = 0; i < 3; i++)
661     northKeyCode[i] = keycodes[i + 0];
662   for (i = 0; i < 3; i++)
663     eastKeyCode[i] = keycodes[i + 3];
664   for (i = 0; i < 3; i++)
665     southKeyCode[i] = keycodes[i + 6];
666   for (i = 0; i < 3; i++)
667     westKeyCode[i] = keycodes[i + 9];
668   for (i = 0; i < 3; i++)
669     fireKeyCode[i] = keycodes[i + 12];
670   for (i = 0; i < 1; i++)
671     escKeyCode[i] = keycodes[i + 15];
672
673   /* ----------------------------------------------------------------- */
674
675 #if 0
676   {
677     Bitmap *bm = pcxBitmaps[2];
678     Pixmap clip_mask = bm->clip_mask;
679
680     if (clip_mask)
681     {
682 #if 1
683       int width = bm->width;
684       int height = bm->height;
685 #else
686       int width = 16 * 4;
687       int height = 16 * 4;
688 #endif
689       XImage *src_ximage = XGetImage(display, clip_mask, 0, 0,
690                                      width, height, AllPlanes, ZPixmap);
691       XImage *dst_ximage = XGetImage(display, xwindow, 0, 0,
692                                      width, height, AllPlanes, ZPixmap);
693       int x, y;
694
695       if (src_ximage == NULL)
696       {
697         printf("src_ximage failed\n");
698         exit(1);
699       }
700
701       if (dst_ximage == NULL)
702       {
703         printf("dst_ximage failed\n");
704         exit(1);
705       }
706
707       printf("::: DISPLAY CLIP MASK ...\n");
708
709       for (x=0; x<width; x++)
710       {
711         for (y=0; y<height; y++)
712         {
713           unsigned long pixel = XGetPixel(src_ximage, x, y);
714
715           if (pixel != BlackPixel(display, screen))
716             pixel = WhitePixel(display, screen);
717
718           XPutPixel(dst_ximage, x, y, pixel);
719         }
720       }
721
722       printf("::: DISPLAY CLIP MASK NOW\n");
723
724       XPutImage(display, xwindow, screenGC, dst_ximage, 0, 0,
725                 0, 13 * TILEY, width, height);
726
727       printf("::: DISPLAY CLIP MASK DONE\n");
728     }
729   }
730 #endif
731
732   /* ----------------------------------------------------------------- */
733
734 #if 0
735   {
736     int ii = 2;
737
738     XGCValues clip_gc_values;
739     unsigned long clip_gc_valuemask;
740
741 #if 1
742     GC gc = screenGC;
743 #else
744 #if 1
745     GC gc = pcxBitmaps[ii]->stored_clip_gc;
746 #else
747     GC gc = pcxBitmaps[ii]->gc;
748 #endif
749 #endif
750     Pixmap src_pixmap = pcxBitmaps[ii]->clip_mask;
751     Pixmap dst_pixmap = pcxBitmapsX2[ii]->clip_mask;
752     int src_width = pcxBitmaps[ii]->width;
753     int src_height = pcxBitmaps[ii]->height;
754     int dst_width = pcxBitmapsX2[ii]->width;
755     int dst_height = pcxBitmapsX2[ii]->height;
756
757     XImage *src_ximage, *dst_ximage;
758     byte *src_ptr, *dst_ptr;
759     int bits_per_pixel;
760     int bytes_per_pixel;
761     int x, y, xx, yy, i;
762 #if 1
763     boolean scale_down = (src_width > dst_width);
764     int zoom_factor;
765 #else
766     int zoom_factor = src_width / dst_width;    /* currently very limited! */
767 #endif
768     int row_skip, col_skip;
769
770     printf("::: %d\n", scale_down);
771
772     xdebug("::: ZOOM STEP 1");
773
774     clip_gc_values.graphics_exposures = False;
775     clip_gc_valuemask = GCGraphicsExposures;
776     if ((gc = XCreateGC(display, pcxBitmaps[ii]->clip_mask,
777                         clip_gc_valuemask, &clip_gc_values)) == None)
778     {
779       printf("XCreateGC failed\n");
780       exit(1);
781     }
782
783     xdebug("::: ZOOM STEP 2");
784
785     if (scale_down)
786     {
787       zoom_factor = src_width / dst_width;
788
789       /* adjust source image size to integer multiple of destination size */
790       src_width  = dst_width  * zoom_factor;
791       src_height = dst_height * zoom_factor;
792     }
793     else
794     {
795       zoom_factor = dst_width / src_width;
796
797       /* no adjustment needed when scaling up (some pixels may be left blank) */
798     }
799
800     /* copy source pixmap to temporary image */
801     if ((src_ximage = XGetImage(display, src_pixmap, 0, 0, src_width, src_height,
802                                 AllPlanes, ZPixmap)) == NULL)
803       Error(ERR_EXIT, "ZoomPixmap(): XGetImage() failed");
804
805     bits_per_pixel = src_ximage->bits_per_pixel;
806     bytes_per_pixel = (bits_per_pixel + 7) / 8;
807
808     printf("::: bits_per_pixel == %d\n", bits_per_pixel);
809
810     if ((dst_ximage = XCreateImage(display, visual, src_ximage->depth, ZPixmap,
811                                    0, NULL, dst_width, dst_height,
812                                    8, dst_width * bytes_per_pixel)) == NULL)
813       Error(ERR_EXIT, "ZoomPixmap(): XC reateImage() failed");
814
815     dst_ximage->data =
816       checked_malloc(dst_width * dst_height * bytes_per_pixel);
817     dst_ximage->byte_order = src_ximage->byte_order;
818
819     src_ptr = (byte *)src_ximage->data;
820     dst_ptr = (byte *)dst_ximage->data;
821
822     if (scale_down)
823     {
824       col_skip = (zoom_factor - 1) * bytes_per_pixel;
825       row_skip = col_skip * src_width;
826
827       /* scale image down by scaling factor 'zoom_factor' */
828       for (y = 0; y < src_height; y += zoom_factor, src_ptr += row_skip)
829         for (x = 0; x < src_width; x += zoom_factor, src_ptr += col_skip)
830           for (i = 0; i < bytes_per_pixel; i++)
831             *dst_ptr++ = *src_ptr++;
832     }
833     else
834     {
835       row_skip = src_width * bytes_per_pixel;
836
837 #if 1
838       printf("::: %d, %d -> %d, %d [%d / %d]\n[%ld -> %ld (%ld)] [%ld -> %ld (%ld)]\n",
839              src_width, src_height,
840              dst_width, dst_height,
841              zoom_factor, bytes_per_pixel,
842              src_ptr,
843              src_ptr + src_width * src_height * bytes_per_pixel,
844              src_width * src_height * bytes_per_pixel,
845              dst_ptr,
846              dst_ptr + dst_width * dst_height * bytes_per_pixel,
847              dst_width * dst_height * bytes_per_pixel);
848 #endif
849
850 #if 0
851       printf("A\n");
852
853       for (i = 0; i < src_width * src_height * bytes_per_pixel;
854            i++)
855       {
856         byte x = *(byte *)(src_ptr + i);
857
858         printf("::: %d ...\n", i);
859
860         x = x * 1;
861       }
862
863       printf("B\n");
864 #endif
865
866       /* scale image up by scaling factor 'zoom_factor' */
867       for (y = 0; y < src_height; y++)
868       {
869         for (yy = 0; yy < zoom_factor; yy++)
870         {
871           if (yy > 0)
872             src_ptr -= row_skip;
873
874 #if 0
875           printf("::: [%d -> %ld / %ld]\n", y, src_ptr, dst_ptr);
876 #endif
877
878           for (x = 0; x < src_width; x++)
879           {
880             for (xx = 0; xx < zoom_factor; xx++)
881               for (i = 0; i < bytes_per_pixel; i++)
882 #if 1
883               {
884 #if 0
885                 printf("::: %d\n", *(src_ptr + i));
886 #endif
887
888                 *dst_ptr++ = *(src_ptr + i);
889               }
890 #else
891             *dst_ptr++ = 0;
892 #endif
893
894             src_ptr += i;
895           }
896         }
897       }
898     }
899
900     xdebug("::: ZOOM STEP 9");
901
902     /* copy scaled image to destination pixmap */
903     XPutImage(display, dst_pixmap, gc, dst_ximage, 0, 0, 0, 0,
904               dst_width, dst_height);
905
906     /* free temporary images */
907     X11DestroyImage(src_ximage);
908     X11DestroyImage(dst_ximage);
909
910
911     xdebug("::: ZOOM DONE");
912
913   }
914 #endif
915
916   /* ----------------------------------------------------------------- */
917
918 #if 0
919   {
920     Bitmap *bm = pcxBitmapsX2[2];
921     Pixmap clip_mask = bm->clip_mask;
922
923     if (clip_mask)
924     {
925 #if 0
926       int width = bm->width;
927       int height = bm->height;
928 #else
929       int width = 16 * 4;
930       int height = 16 * 4;
931 #endif
932       XImage *src_ximage = XGetImage(display, clip_mask, 0, 0,
933                                      width, height, AllPlanes, ZPixmap);
934       XImage *dst_ximage = XGetImage(display, xwindow, 0, 0,
935                                      width, height, AllPlanes, ZPixmap);
936       int x, y;
937
938       if (src_ximage == NULL)
939       {
940         printf("src_ximage failed\n");
941         exit(1);
942       }
943
944       if (dst_ximage == NULL)
945       {
946         printf("dst_ximage failed\n");
947         exit(1);
948       }
949
950       printf("::: DISPLAY CLIP MASK ...\n");
951
952       for (x=0; x<width; x++)
953       {
954         for (y=0; y<height; y++)
955         {
956           unsigned long pixel = XGetPixel(src_ximage, x, y);
957
958           if (pixel != BlackPixel(display, screen))
959             pixel = WhitePixel(display, screen);
960
961           XPutPixel(dst_ximage, x, y, pixel);
962         }
963       }
964
965       printf("::: DISPLAY CLIP MASK NOW\n");
966
967       XPutImage(display, xwindow, screenGC, dst_ximage, 0, 0,
968                 0, 13 * TILEY + height, width, height);
969
970       printf("::: DISPLAY CLIP MASK DONE\n");
971     }
972   }
973 #endif
974
975   /* ----------------------------------------------------------------- */
976
977 #if 0
978   {
979     XImage *dst_ximage;
980
981     printf("::: GET IMAGE ...\n");
982
983     dst_ximage = XGetImage(display, xwindow, 0, 0,
984                            16, 16, AllPlanes, ZPixmap);
985     if (dst_ximage == NULL)
986     {
987       printf("dst_ximage failed\n");
988       exit(1);
989     }
990
991     printf("::: PUT IMAGE ...\n");
992
993     XPutImage(display, xwindow, screenGC, dst_ximage, 0, 0,
994               0, 13 * TILEY, 10, 10);
995
996     printf("::: PUT IMAGE DONE\n");
997   }
998 #endif
999
1000   /* ----------------------------------------------------------------- */
1001
1002 #if defined(PLATFORM_LINUX) || defined(PLATFORM_BSD)
1003   if (arg_silence == 0)
1004   {
1005     for (i = 0; i < SAMPLE_MAX; i++)
1006     {
1007       name[MAXNAME] = 0;
1008
1009       if (arg_basedir)
1010       {
1011         snprintf(name, MAXNAME+2, "%s/%s/%s", arg_basedir, EM_SND_DIR,
1012                  sound_names[i]);
1013       }
1014       else
1015       {
1016         snprintf(name, MAXNAME+2, "%s/%s", EM_SND_DIR, sound_names[i]);
1017       }
1018
1019       if (name[MAXNAME]) snprintf_overflow("read sounds/ directory");
1020
1021       if (read_sample(name, &sound_data[i], &sound_length[i]))
1022         return(1);
1023
1024       {
1025         short *ptr, *stop;
1026         int mult = sound_volume[i] * 65536 / (100 * MIXER_MAX);
1027         stop = sound_data[i] + sound_length[i];
1028         for (ptr = sound_data[i]; ptr < stop; ptr++)
1029           *ptr = (*ptr * mult) / 65536;
1030       }
1031     }
1032
1033     if (pipe(sound_pipe) == -1)
1034     {
1035       fprintf(stderr, "%s: %s: %s\n", progname, "unable to create sound pipe",
1036               strerror(errno));
1037       return(1);
1038     }
1039
1040     sound_pid = fork();
1041     if (sound_pid == -1)
1042     {
1043       fprintf(stderr, "%s: %s: %s\n", progname, "unable to fork sound thread",
1044               strerror(errno));
1045       return(1);
1046     }
1047
1048     close(sound_pipe[sound_pid == 0]); sound_pipe[sound_pid == 0] = -1;
1049     if (sound_pid == 0)
1050       _exit(sound_thread());
1051
1052     signal(SIGPIPE, SIG_IGN); /* dont crash if sound process dies */
1053   }
1054
1055 #endif /* defined(PLATFORM_LINUX) || defined(PLATFORM_BSD) */
1056
1057   return(0);
1058 }
1059
1060 void close_all(void)
1061 {
1062   int i;
1063
1064   if (sound_pid != -1)
1065   {
1066     kill(sound_pid, SIGTERM);
1067     waitpid(sound_pid, 0, 0);
1068   }
1069
1070   if (sound_pipe[0] != -1)
1071     close(sound_pipe[0]);
1072   if (sound_pipe[1] != -1)
1073     close(sound_pipe[1]);
1074
1075   for (i = 0; i < SAMPLE_MAX; i++)
1076     if (sound_data[i])
1077       free(sound_data[i]);
1078
1079 #if 0
1080   for (i = 0; i < 4; i++)
1081     if (xpmPixmaps[i])
1082       XFreePixmap(display, xpmPixmaps[i]);
1083   for (i = 0; i < 4; i++)
1084     if (xpmBitmaps[i])
1085       XFreePixmap(display, xpmBitmaps[i]);
1086   for (i = 0; i < 4; i++)
1087     if (xpmGot[i])
1088     {
1089       xpmFreeColoursFunc(display, xpmAttributes[i].colormap,
1090                          xpmAttributes[i].alloc_pixels,
1091                          xpmAttributes[i].nalloc_pixels, 0);
1092       XpmFreeAttributes(&xpmAttributes[i]);
1093     }
1094 #endif
1095
1096   if (gotRed)
1097     xpmFreeColoursFunc(display,
1098                        privateColourmap ? privateColourmap : defaultColourmap,
1099                        &redColour.pixel, 1, 0);
1100   if (gotWhite)
1101     xpmFreeColoursFunc(display,
1102                        privateColourmap ? privateColourmap : defaultColourmap,
1103                        &whiteColour.pixel, 1, 0);
1104
1105   if (screenGC)
1106     XFreeGC(display, screenGC);
1107   if (scoreGC)
1108     XFreeGC(display, scoreGC);
1109   if (spriteGC)
1110     XFreeGC(display, spriteGC);
1111   if (antsGC)
1112     XFreeGC(display, antsGC);
1113   if (screenPixmap)
1114     XFreePixmap(display, screenPixmap);
1115   if (scorePixmap)
1116     XFreePixmap(display, scorePixmap);
1117   if (spriteBitmap)
1118     XFreePixmap(display, spriteBitmap);
1119   if (xwindow)
1120     XDestroyWindow(display, xwindow);
1121   if (cursor)
1122     XFreeCursor(display, cursor);
1123   if (privateColourmap)
1124     XFreeColormap(display, privateColourmap);
1125   if (privateColours)
1126     free(privateColours);
1127   if (privateFlags)
1128     free(privateFlags);
1129 #if 0
1130   if (display)
1131     XCloseDisplay(display);
1132 #endif
1133 }
1134
1135 /* ---------------------------------------------------------------------- */
1136
1137 void sound_play(void)
1138 {
1139   if (sound_pipe[1] != -1)
1140   {
1141     if (write(sound_pipe[1], &play, sizeof(play)) == -1)
1142     {
1143       fprintf(stderr, "%s: %s: %s\n", progname, "write sound",
1144               strerror(errno));
1145
1146       if (sound_pipe[0] != -1)
1147       {
1148         close(sound_pipe[0]);
1149         sound_pipe[0] = -1;
1150       }
1151
1152       if (sound_pipe[1] != -1)
1153       {
1154         close(sound_pipe[1]);
1155         sound_pipe[1] = -1;
1156       }
1157     }
1158   }
1159
1160   memset(play, 0, sizeof(play));
1161 }
1162
1163 /* ---------------------------------------------------------------------- */
1164
1165 static int xpmAllocColourFunc(Display *display, Colormap colourmap,
1166                               char *colourname, XColor *xcolour, void *closure)
1167 {
1168   int i, match;
1169   int r,g,b;
1170   long best, sum;
1171
1172   if (colourname)
1173     if (XParseColor(display, colourmap, colourname, xcolour) == 0)
1174       return(-1); /* invalid name */
1175   if (colourmap != privateColourmap)
1176     return(XAllocColor(display, colourmap, xcolour) != 0);
1177
1178   /* first try to find an exact match */
1179   match = -1;
1180   for (i = 0; i < privateNumColours; i++)
1181   {
1182     if (privateColours[i].red == xcolour->red &&
1183         privateColours[i].green == xcolour->green &&
1184         privateColours[i].blue == xcolour->blue)
1185       match = i;
1186   }
1187
1188   if (match != -1)
1189   {
1190     privateFlags[match] = 1;
1191     xcolour->pixel = privateColours[match].pixel;
1192     return(1);
1193   }
1194
1195   /* then find an unallocated colour that is close to what we want */
1196   match = -1;
1197   best = 1000000;
1198   for (i = 0; i < privateNumColours; i++)
1199   {
1200     if (privateFlags[i])
1201       continue; /* skip if it is already allocated */
1202
1203     r = (privateColours[i].red - xcolour->red) / 256;
1204     g = (privateColours[i].green - xcolour->green) / 256;
1205     b = (privateColours[i].blue - xcolour->blue) / 256;
1206     sum = r * r + g * g + b * b;
1207
1208     if (sum < best)
1209     {
1210       best = sum;
1211       match = i;
1212     }
1213   }
1214
1215   if (match != -1)
1216   {
1217     privateFlags[match] = 1;
1218     privateColours[match].red = xcolour->red;
1219     privateColours[match].green = xcolour->green;
1220     privateColours[match].blue = xcolour->blue;
1221     XStoreColor(display, colourmap, &privateColours[match]);
1222     xcolour->pixel = privateColours[match].pixel;
1223     return(1); /* found a close match */
1224   }
1225
1226   /* if all else fails, just find the closest colour and return it */
1227   match = -1;
1228   best = 1000000;
1229   for (i = 0; i < privateNumColours; i++)
1230   {
1231     r = (privateColours[i].red - xcolour->red) / 256;
1232     g = (privateColours[i].green - xcolour->green) / 256;
1233     b = (privateColours[i].blue - xcolour->blue) / 256;
1234     sum = r * r + g * g + b * b;
1235
1236     if (sum < best)
1237     {
1238       best = sum;
1239       match = i;
1240     }
1241   }
1242
1243   if (match != -1)
1244   {
1245     xcolour->red = privateColours[match].red;
1246     xcolour->green = privateColours[match].green;
1247     xcolour->blue = privateColours[match].blue;
1248     xcolour->pixel = privateColours[match].pixel;
1249     return(1); /* best we could do */
1250   }
1251
1252   return(0); /* still didnt find one, give up */
1253 }
1254
1255 static int xpmFreeColoursFunc(Display *display, Colormap colourmap,
1256                               unsigned long *pixels, int npixels,
1257                               void *closure)
1258 {
1259   if (colourmap != privateColourmap)
1260     XFreeColors(display, colourmap, pixels, npixels, 0);
1261
1262   return(1); /* non-zero for success */
1263 }
1264
1265 #endif