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