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