rnd-20040820-1-src
[rocksndiamonds.git] / src / game_em / init.c
1 /* 2000-08-10T18:03:54Z
2  *
3  * open X11 display and sound
4  */
5
6 #if 1
7 #include <X11/Xlib.h>
8 #include <X11/Xutil.h>
9 #include <X11/Xatom.h>
10 #include <X11/Xos.h>
11 #include <X11/Intrinsic.h>
12 #include <X11/keysymdef.h>
13 #endif
14
15 #include <X11/Xlib.h>
16 #include <X11/Xutil.h>
17 #include <X11/Xatom.h>
18 #include <X11/keysym.h>
19 #include <X11/cursorfont.h>
20 #include <X11/xpm.h>
21 #include <sys/types.h>
22 #include <sys/wait.h>
23 #include <unistd.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <signal.h>
27 #include <string.h>
28 #include <errno.h>
29
30 #include "../libgame/platform.h"
31 #include "../libgame/libgame.h"
32
33 #include "global.h"
34 #include "display.h"
35 #include "sample.h"
36
37
38 #if defined(TARGET_X11)
39
40 #if 0
41 Display *display;
42 Window xwindow;
43 #endif
44
45 #if 1
46 Bitmap *objBitmap;
47 Bitmap *botBitmap;
48 Bitmap *sprBitmap;
49 Bitmap *ttlBitmap;
50 #endif
51
52 #if 1
53 Bitmap *screenBitmap;
54 Bitmap *scoreBitmap;
55 #endif
56
57 Pixmap screenPixmap;
58 Pixmap scorePixmap;
59 Pixmap spriteBitmap;
60
61 Pixmap objPixmap;
62 Pixmap objmaskBitmap;
63 Pixmap botPixmap;
64 Pixmap botmaskBitmap;
65 Pixmap sprPixmap;
66 Pixmap sprmaskBitmap;
67 Pixmap ttlPixmap;
68 Pixmap ttlmaskBitmap;
69
70 GC screenGC;
71 GC scoreGC;
72 GC spriteGC;
73 GC antsGC;
74
75 Atom deleteAtom;
76
77 KeySym lastKeySym;
78
79 KeyCode northKeyCode[3];
80 KeyCode eastKeyCode[3];
81 KeyCode southKeyCode[3];
82 KeyCode westKeyCode[3];
83 KeyCode fireKeyCode[3];
84 KeyCode escKeyCode[1];
85
86 char play[SAMPLE_MAX];
87
88 static int sound_pid = -1;
89 int sound_pipe[2] = { -1, -1 }; /* for communication */
90 short *sound_data[SAMPLE_MAX]; /* pointer to sound data */
91 long sound_length[SAMPLE_MAX]; /* length of sound data */
92
93 static Screen *defaultScreen;
94 static Visual *defaultVisual;
95 static Colormap defaultColourmap;
96 static Window defaultRootWindow;
97 static unsigned int screenDepth;
98 static unsigned int screenWidth;
99 static unsigned int screenHeight;
100 static unsigned long screenBlackPixel;
101 static unsigned long screenWhitePixel;
102
103 #if 0
104 static XSizeHints sizeHints;
105 static XSetWindowAttributes setWindowAttributes;
106 static XWMHints wmHints;
107 static XVisualInfo visualInfo;
108 #endif
109 static XGCValues gcValues;
110
111 static Colormap privateColourmap;
112 static Cursor cursor;
113 static XColor *privateColours;
114 static unsigned char *privateFlags;
115 static int privateNumColours;
116
117 static XColor redColour;
118 static XColor whiteColour;
119 static int gotRed;
120 static int gotWhite;
121
122 #if 1
123 static Bitmap *pcxBitmaps[4];
124 static Bitmap *pcxBitmapsX2[4];
125 #endif
126
127 #if 0
128 static Pixmap xpmPixmaps[4];
129 static Pixmap xpmBitmaps[4];
130 static XpmAttributes xpmAttributes[4];
131 static int xpmGot[4];
132 #endif
133
134 static int xpmAllocColourFunc(Display *, Colormap, char *, XColor *, void *);
135 static int xpmFreeColoursFunc(Display *, Colormap, unsigned long *, int, void *);
136
137 static KeyCode keycodes[16];
138
139 #if 0
140 static const char *xpmNames[4] = { "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 #if 0
443           printf("::: %ld, %ld, %ld, %ld, %ld, %ld, %ld\n",
444                  pcxBitmaps[i]->gc,
445                  pcxBitmaps[i]->clip_mask, pcxBitmapsX2[i]->clip_mask,
446                  pcxBitmaps[i]->width, pcxBitmaps[i]->height,
447                  pcxBitmapsX2[i]->width, pcxBitmapsX2[i]->height);
448 #endif
449
450 #if 0
451           ZoomPixmap(display, pcxBitmaps[i]->gc,
452                      pcxBitmaps[i]->clip_mask, pcxBitmapsX2[i]->clip_mask,
453                      pcxBitmaps[i]->width, pcxBitmaps[i]->height,
454                      pcxBitmapsX2[i]->width, pcxBitmapsX2[i]->height);
455 #endif
456
457 #endif
458         }
459
460         objBitmap = pcxBitmapsX2[0];
461         botBitmap = pcxBitmapsX2[1];
462         sprBitmap = pcxBitmapsX2[2];
463         ttlBitmap = pcxBitmapsX2[3];
464
465         objPixmap = pcxBitmapsX2[0]->drawable;
466         botPixmap = pcxBitmapsX2[1]->drawable;
467         sprPixmap = pcxBitmapsX2[2]->drawable;
468         ttlPixmap = pcxBitmapsX2[3]->drawable;
469 #if 1
470         objmaskBitmap = pcxBitmapsX2[0]->clip_mask;
471         botmaskBitmap = pcxBitmapsX2[1]->clip_mask;
472         sprmaskBitmap = pcxBitmapsX2[2]->clip_mask;
473         ttlmaskBitmap = pcxBitmapsX2[3]->clip_mask;
474 #endif
475 #endif
476
477 #if 1
478         screenBitmap = CreateBitmap(22 * TILEX, 14 * TILEY, DEFAULT_DEPTH);
479         scoreBitmap = CreateBitmap(20 * TILEX, SCOREY, DEFAULT_DEPTH);
480 #endif
481
482         screenPixmap = XCreatePixmap(display, xwindow, 22 * TILEX, 14 * TILEY, screenDepth);
483         if(screenPixmap == 0) {
484                 fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, XDisplayName(arg_display), "failed to create pixmap", strerror(errno));
485                 return(1);
486         }
487
488         scorePixmap = XCreatePixmap(display, xwindow, 20 * TILEX, SCOREY, screenDepth);
489         if(scorePixmap == 0) {
490                 fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, XDisplayName(arg_display), "failed to create pixmap", strerror(errno));
491                 return(1);
492         }
493
494         spriteBitmap = XCreatePixmap(display, xwindow, TILEX, TILEY, 1);
495         if(spriteBitmap == 0) {
496                 fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, XDisplayName(arg_display), "failed to create pixmap", strerror(errno));
497                 return(1);
498         }
499
500         redColour.pixel = screenWhitePixel;
501         whiteColour.pixel = screenBlackPixel;
502         gotRed = (xpmAllocColourFunc(display, privateColourmap ? privateColourmap : defaultColourmap, "red", &redColour, 0) > 0);
503         gotWhite = (xpmAllocColourFunc(display, privateColourmap ? privateColourmap : defaultColourmap, "white", &whiteColour, 0) > 0);
504
505         gcValues.graphics_exposures = False;
506         screenGC = XCreateGC(display, screenPixmap, GCGraphicsExposures, &gcValues);
507         if(screenGC == 0) {
508                 fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, XDisplayName(arg_display), "failed to create graphics context", strerror(errno));
509                 return(1);
510         }
511
512         gcValues.graphics_exposures = False;
513         scoreGC = XCreateGC(display, scorePixmap, GCGraphicsExposures, &gcValues);
514         if(scoreGC == 0) {
515                 fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, XDisplayName(arg_display), "failed to create graphics context", strerror(errno));
516                 return(1);
517         }
518
519         gcValues.function = objmaskBitmap ? GXcopyInverted : sprmaskBitmap ? GXcopy : GXset;
520         gcValues.graphics_exposures = False;
521         spriteGC = XCreateGC(display, spriteBitmap, GCFunction | GCGraphicsExposures, &gcValues);
522         if(spriteGC == 0) {
523                 fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, XDisplayName(arg_display), "failed to create graphics context", strerror(errno));
524                 return(1);
525         }
526
527         gcValues.foreground = redColour.pixel;
528         gcValues.background = whiteColour.pixel;
529         gcValues.line_style = LineDoubleDash;
530         gcValues.graphics_exposures = False;
531         antsGC = XCreateGC(display, screenPixmap, GCForeground | GCBackground | GCLineStyle | GCGraphicsExposures, &gcValues);
532         if(antsGC == 0) {
533                 fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, XDisplayName(arg_display), "failed to create graphics context", strerror(errno));
534                 return(1);
535         }
536
537         for(i = 0; i < 16; i++) {
538                 keycodes[i] = XKeysymToKeycode(display, keysyms[i]);
539         }
540         for(i = 0; i < 3; i++) northKeyCode[i] = keycodes[i + 0];
541         for(i = 0; i < 3; i++) eastKeyCode[i] = keycodes[i + 3];
542         for(i = 0; i < 3; i++) southKeyCode[i] = keycodes[i + 6];
543         for(i = 0; i < 3; i++) westKeyCode[i] = keycodes[i + 9];
544         for(i = 0; i < 3; i++) fireKeyCode[i] = keycodes[i + 12];
545         for(i = 0; i < 1; i++) escKeyCode[i] = keycodes[i + 15];
546
547         /* ----------------------------------------------------------------- */
548
549 #if 0
550         {
551           Bitmap *bm = pcxBitmaps[2];
552           Pixmap clip_mask = bm->clip_mask;
553
554           if (clip_mask)
555           {
556 #if 1
557             int width = bm->width;
558             int height = bm->height;
559 #else
560             int width = 16 * 4;
561             int height = 16 * 4;
562 #endif
563             XImage *src_ximage = XGetImage(display, clip_mask, 0, 0,
564                                            width, height, AllPlanes, ZPixmap);
565             XImage *dst_ximage = XGetImage(display, xwindow, 0, 0,
566                                            width, height, AllPlanes, ZPixmap);
567             int x, y;
568
569             if (src_ximage == NULL)
570             {
571               printf("src_ximage failed\n");
572               exit(1);
573             }
574
575             if (dst_ximage == NULL)
576             {
577               printf("dst_ximage failed\n");
578               exit(1);
579             }
580
581             printf("::: DISPLAY CLIP MASK ...\n");
582
583             for (x=0; x<width; x++)
584             {
585               for (y=0; y<height; y++)
586               {
587                 unsigned long pixel = XGetPixel(src_ximage, x, y);
588
589                 if (pixel != BlackPixel(display, screen))
590                   pixel = WhitePixel(display, screen);
591
592                 XPutPixel(dst_ximage, x, y, pixel);
593               }
594             }
595
596             printf("::: DISPLAY CLIP MASK NOW\n");
597
598             XPutImage(display, xwindow, screenGC, dst_ximage, 0, 0,
599                       0, 13 * TILEY, width, height);
600
601             printf("::: DISPLAY CLIP MASK DONE\n");
602           }
603         }
604 #endif
605
606         /* ----------------------------------------------------------------- */
607
608 #if 0
609         {
610           int ii = 2;
611
612           XGCValues clip_gc_values;
613           unsigned long clip_gc_valuemask;
614
615 #if 1
616           GC gc = screenGC;
617 #else
618 #if 1
619           GC gc = pcxBitmaps[ii]->stored_clip_gc;
620 #else
621           GC gc = pcxBitmaps[ii]->gc;
622 #endif
623 #endif
624           Pixmap src_pixmap = pcxBitmaps[ii]->clip_mask;
625           Pixmap dst_pixmap = pcxBitmapsX2[ii]->clip_mask;
626           int src_width = pcxBitmaps[ii]->width;
627           int src_height = pcxBitmaps[ii]->height;
628           int dst_width = pcxBitmapsX2[ii]->width;
629           int dst_height = pcxBitmapsX2[ii]->height;
630
631   XImage *src_ximage, *dst_ximage;
632   byte *src_ptr, *dst_ptr;
633   int bits_per_pixel;
634   int bytes_per_pixel;
635   int x, y, xx, yy, i;
636 #if 1
637   boolean scale_down = (src_width > dst_width);
638   int zoom_factor;
639 #else
640   int zoom_factor = src_width / dst_width;      /* currently very limited! */
641 #endif
642   int row_skip, col_skip;
643
644   printf("::: %d\n", scale_down);
645
646   xdebug("::: ZOOM STEP 1");
647
648   clip_gc_values.graphics_exposures = False;
649   clip_gc_valuemask = GCGraphicsExposures;
650   if ((gc = XCreateGC(display, pcxBitmaps[ii]->clip_mask,
651                       clip_gc_valuemask, &clip_gc_values)) == None)
652   {
653     printf("XCreateGC failed\n");
654     exit(1);
655   }
656
657   xdebug("::: ZOOM STEP 2");
658
659   if (scale_down)
660   {
661     zoom_factor = src_width / dst_width;
662
663     /* adjust source image size to integer multiple of destination size */
664     src_width  = dst_width  * zoom_factor;
665     src_height = dst_height * zoom_factor;
666   }
667   else
668   {
669     zoom_factor = dst_width / src_width;
670
671     /* no adjustment needed when scaling up (some pixels may be left blank) */
672   }
673
674   /* copy source pixmap to temporary image */
675   if ((src_ximage = XGetImage(display, src_pixmap, 0, 0, src_width, src_height,
676                               AllPlanes, ZPixmap)) == NULL)
677     Error(ERR_EXIT, "ZoomPixmap(): XGetImage() failed");
678
679   bits_per_pixel = src_ximage->bits_per_pixel;
680   bytes_per_pixel = (bits_per_pixel + 7) / 8;
681
682   printf("::: bits_per_pixel == %d\n", bits_per_pixel);
683
684   if ((dst_ximage = XCreateImage(display, visual, src_ximage->depth, ZPixmap,
685                                  0, NULL, dst_width, dst_height,
686                                  8, dst_width * bytes_per_pixel)) == NULL)
687     Error(ERR_EXIT, "ZoomPixmap(): XCreateImage() failed");
688
689   dst_ximage->data =
690     checked_malloc(dst_width * dst_height * bytes_per_pixel);
691   dst_ximage->byte_order = src_ximage->byte_order;
692
693   src_ptr = (byte *)src_ximage->data;
694   dst_ptr = (byte *)dst_ximage->data;
695
696   if (scale_down)
697   {
698     col_skip = (zoom_factor - 1) * bytes_per_pixel;
699     row_skip = col_skip * src_width;
700
701     /* scale image down by scaling factor 'zoom_factor' */
702     for (y = 0; y < src_height; y += zoom_factor, src_ptr += row_skip)
703       for (x = 0; x < src_width; x += zoom_factor, src_ptr += col_skip)
704         for (i = 0; i < bytes_per_pixel; i++)
705           *dst_ptr++ = *src_ptr++;
706   }
707   else
708   {
709     row_skip = src_width * bytes_per_pixel;
710
711 #if 1
712     printf("::: %d, %d -> %d, %d [%d / %d]\n[%ld -> %ld (%ld)] [%ld -> %ld (%ld)]\n",
713            src_width, src_height,
714            dst_width, dst_height,
715            zoom_factor, bytes_per_pixel,
716            src_ptr,
717            src_ptr + src_width * src_height * bytes_per_pixel,
718            src_width * src_height * bytes_per_pixel,
719            dst_ptr,
720            dst_ptr + dst_width * dst_height * bytes_per_pixel,
721            dst_width * dst_height * bytes_per_pixel);
722 #endif
723
724 #if 0
725     printf("A\n");
726
727     for (i = 0; i < src_width * src_height * bytes_per_pixel;
728          i++)
729     {
730       byte x = *(byte *)(src_ptr + i);
731
732       printf("::: %d ...\n", i);
733
734       x = x * 1;
735     }
736
737     printf("B\n");
738 #endif
739
740     /* scale image up by scaling factor 'zoom_factor' */
741     for (y = 0; y < src_height; y++)
742     {
743       for (yy = 0; yy < zoom_factor; yy++)
744       {
745         if (yy > 0)
746           src_ptr -= row_skip;
747
748 #if 0
749         printf("::: [%d -> %ld / %ld]\n", y, src_ptr, dst_ptr);
750 #endif
751
752         for (x = 0; x < src_width; x++)
753         {
754           for (xx = 0; xx < zoom_factor; xx++)
755             for (i = 0; i < bytes_per_pixel; i++)
756 #if 1
757             {
758 #if 0
759               printf("::: %d\n", *(src_ptr + i));
760 #endif
761
762               *dst_ptr++ = *(src_ptr + i);
763             }
764 #else
765               *dst_ptr++ = 0;
766 #endif
767
768           src_ptr += i;
769         }
770       }
771     }
772   }
773
774   xdebug("::: ZOOM STEP 9");
775
776   /* copy scaled image to destination pixmap */
777   XPutImage(display, dst_pixmap, gc, dst_ximage, 0, 0, 0, 0,
778             dst_width, dst_height);
779
780   /* free temporary images */
781   X11DestroyImage(src_ximage);
782   X11DestroyImage(dst_ximage);
783
784
785   xdebug("::: ZOOM DONE");
786
787         }
788 #endif
789
790         /* ----------------------------------------------------------------- */
791
792 #if 0
793         {
794           Bitmap *bm = pcxBitmapsX2[2];
795           Pixmap clip_mask = bm->clip_mask;
796
797           if (clip_mask)
798           {
799 #if 0
800             int width = bm->width;
801             int height = bm->height;
802 #else
803             int width = 16 * 4;
804             int height = 16 * 4;
805 #endif
806             XImage *src_ximage = XGetImage(display, clip_mask, 0, 0,
807                                            width, height, AllPlanes, ZPixmap);
808             XImage *dst_ximage = XGetImage(display, xwindow, 0, 0,
809                                            width, height, AllPlanes, ZPixmap);
810             int x, y;
811
812             if (src_ximage == NULL)
813             {
814               printf("src_ximage failed\n");
815               exit(1);
816             }
817
818             if (dst_ximage == NULL)
819             {
820               printf("dst_ximage failed\n");
821               exit(1);
822             }
823
824             printf("::: DISPLAY CLIP MASK ...\n");
825
826             for (x=0; x<width; x++)
827             {
828               for (y=0; y<height; y++)
829               {
830                 unsigned long pixel = XGetPixel(src_ximage, x, y);
831
832                 if (pixel != BlackPixel(display, screen))
833                   pixel = WhitePixel(display, screen);
834
835                 XPutPixel(dst_ximage, x, y, pixel);
836               }
837             }
838
839             printf("::: DISPLAY CLIP MASK NOW\n");
840
841             XPutImage(display, xwindow, screenGC, dst_ximage, 0, 0,
842                       0, 13 * TILEY + height, width, height);
843
844             printf("::: DISPLAY CLIP MASK DONE\n");
845           }
846         }
847 #endif
848
849         /* ----------------------------------------------------------------- */
850
851 #if 0
852           {
853             XImage *dst_ximage;
854
855             printf("::: GET IMAGE ...\n");
856
857             dst_ximage = XGetImage(display, xwindow, 0, 0,
858                                    16, 16, AllPlanes, ZPixmap);
859             if (dst_ximage == NULL)
860             {
861               printf("dst_ximage failed\n");
862               exit(1);
863             }
864
865             printf("::: PUT IMAGE ...\n");
866
867             XPutImage(display, xwindow, screenGC, dst_ximage, 0, 0,
868                       0, 13 * TILEY, 10, 10);
869
870             printf("::: PUT IMAGE DONE\n");
871           }
872 #endif
873
874         /* ----------------------------------------------------------------- */
875
876 #if defined(PLATFORM_LINUX) || defined(PLATFORM_BSD)
877         if(arg_silence == 0) {
878                 for(i = 0; i < SAMPLE_MAX; i++) {
879                         name[MAXNAME] = 0;
880                         if(arg_basedir) {
881                                 snprintf(name, MAXNAME+2, "%s/%s/%s", arg_basedir, EM_SND_DIR, sound_names[i]);
882                         } else {
883                                 snprintf(name, MAXNAME+2, "%s/%s", EM_SND_DIR, sound_names[i]);
884                         }
885                         if(name[MAXNAME]) snprintf_overflow("read sounds/ directory");
886
887                         if(read_sample(name, &sound_data[i], &sound_length[i])) return(1);
888
889                         {
890                                 short *ptr, *stop;
891                                 int mult = sound_volume[i] * 65536 / (100 * MIXER_MAX);
892                                 stop = sound_data[i] + sound_length[i];
893                                 for(ptr = sound_data[i]; ptr < stop; ptr++) *ptr = (*ptr * mult) / 65536;
894                         }
895                 }
896
897                 if(pipe(sound_pipe) == -1) {
898                         fprintf(stderr, "%s: %s: %s\n", progname, "unable to create sound pipe", strerror(errno));
899                         return(1);
900                 }
901                 sound_pid = fork();
902                 if(sound_pid == -1) {
903                         fprintf(stderr, "%s: %s: %s\n", progname, "unable to fork sound thread", strerror(errno));
904                         return(1);
905                 }
906                 close(sound_pipe[sound_pid == 0]); sound_pipe[sound_pid == 0] = -1;
907                 if(sound_pid == 0) _exit(sound_thread());
908                 signal(SIGPIPE, SIG_IGN); /* dont crash if sound process dies */
909         }
910 #endif /* defined(PLATFORM_LINUX) || defined(PLATFORM_BSD) */
911
912         return(0);
913 }
914
915 void close_all(void)
916 {
917         int i;
918
919         if(sound_pid != -1) {
920                 kill(sound_pid, SIGTERM);
921                 waitpid(sound_pid, 0, 0);
922         }
923         if(sound_pipe[0] != -1) close(sound_pipe[0]);
924         if(sound_pipe[1] != -1) close(sound_pipe[1]);
925         for(i = 0; i < SAMPLE_MAX; i++) if(sound_data[i]) free(sound_data[i]);
926
927 #if 0
928         for(i = 0; i < 4; i++) if(xpmPixmaps[i]) XFreePixmap(display, xpmPixmaps[i]);
929         for(i = 0; i < 4; i++) if(xpmBitmaps[i]) XFreePixmap(display, xpmBitmaps[i]);
930         for(i = 0; i < 4; i++) if(xpmGot[i]) {
931                 xpmFreeColoursFunc(display, xpmAttributes[i].colormap, xpmAttributes[i].alloc_pixels, xpmAttributes[i].nalloc_pixels, 0);
932                 XpmFreeAttributes(&xpmAttributes[i]);
933         }
934 #endif
935
936         if(gotRed) xpmFreeColoursFunc(display, privateColourmap ? privateColourmap : defaultColourmap, &redColour.pixel, 1, 0);
937         if(gotWhite) xpmFreeColoursFunc(display, privateColourmap ? privateColourmap : defaultColourmap, &whiteColour.pixel, 1, 0);
938
939         if(screenGC) XFreeGC(display, screenGC);
940         if(scoreGC) XFreeGC(display, scoreGC);
941         if(spriteGC) XFreeGC(display, spriteGC);
942         if(antsGC) XFreeGC(display, antsGC);
943         if(screenPixmap) XFreePixmap(display, screenPixmap);
944         if(scorePixmap) XFreePixmap(display, scorePixmap);
945         if(spriteBitmap) XFreePixmap(display, spriteBitmap);
946         if(xwindow) XDestroyWindow(display, xwindow);
947         if(cursor) XFreeCursor(display, cursor);
948         if(privateColourmap) XFreeColormap(display, privateColourmap);
949         if(privateColours) free(privateColours);
950         if(privateFlags) free(privateFlags);
951         if(display) XCloseDisplay(display);
952 }
953
954 /* ---------------------------------------------------------------------- */
955
956 void sound_play(void)
957 {
958         if(sound_pipe[1] != -1) {
959                 if(write(sound_pipe[1], &play, sizeof(play)) == -1) {
960                         fprintf(stderr, "%s: %s: %s\n", progname, "write sound", strerror(errno));
961                         if(sound_pipe[0] != -1) { close(sound_pipe[0]); sound_pipe[0] = -1; }
962                         if(sound_pipe[1] != -1) { close(sound_pipe[1]); sound_pipe[1] = -1; }
963                 }
964         }
965         memset(play, 0, sizeof(play));
966 }
967
968 /* ---------------------------------------------------------------------- */
969
970 static int xpmAllocColourFunc(Display *display, Colormap colourmap, char *colourname, XColor *xcolour, void *closure)
971 {
972         int i, match;
973         int r,g,b;
974         long best, sum;
975
976         if(colourname) if(XParseColor(display, colourmap, colourname, xcolour) == 0) return(-1); /* invalid name */
977         if(colourmap != privateColourmap) return(XAllocColor(display, colourmap, xcolour) != 0);
978
979 /* first try to find an exact match */
980         match = -1;
981         for(i = 0; i < privateNumColours; i++) {
982                 if(privateColours[i].red == xcolour->red && privateColours[i].green == xcolour->green && privateColours[i].blue == xcolour->blue) match = i;
983         }
984         if(match != -1) {
985                 privateFlags[match] = 1;
986                 xcolour->pixel = privateColours[match].pixel;
987                 return(1);
988         }
989
990 /* then find an unallocated colour that is close to what we want */
991         match = -1;
992         best = 1000000;
993         for(i = 0; i < privateNumColours; i++) {
994                 if(privateFlags[i]) continue; /* skip if it is already allocated */
995                 r = (privateColours[i].red - xcolour->red) / 256;
996                 g = (privateColours[i].green - xcolour->green) / 256;
997                 b = (privateColours[i].blue - xcolour->blue) / 256;
998                 sum = r * r + g * g + b * b;
999                 if(sum < best) {
1000                         best = sum;
1001                         match = i;
1002                 }
1003         }
1004         if(match != -1) {
1005                 privateFlags[match] = 1;
1006                 privateColours[match].red = xcolour->red;
1007                 privateColours[match].green = xcolour->green;
1008                 privateColours[match].blue = xcolour->blue;
1009                 XStoreColor(display, colourmap, &privateColours[match]);
1010                 xcolour->pixel = privateColours[match].pixel;
1011                 return(1); /* found a close match */
1012         }
1013
1014 /* if all else fails, just find the closest colour and return it */
1015         match = -1;
1016         best = 1000000;
1017         for(i = 0; i < privateNumColours; i++) {
1018                 r = (privateColours[i].red - xcolour->red) / 256;
1019                 g = (privateColours[i].green - xcolour->green) / 256;
1020                 b = (privateColours[i].blue - xcolour->blue) / 256;
1021                 sum = r * r + g * g + b * b;
1022                 if(sum < best) {
1023                         best = sum;
1024                         match = i;
1025                 }
1026         }
1027         if(match != -1) {
1028                 xcolour->red = privateColours[match].red;
1029                 xcolour->green = privateColours[match].green;
1030                 xcolour->blue = privateColours[match].blue;
1031                 xcolour->pixel = privateColours[match].pixel;
1032                 return(1); /* best we could do */
1033         }
1034         return(0); /* still didnt find one, give up */
1035 }
1036
1037 static int xpmFreeColoursFunc(Display *display, Colormap colourmap, unsigned long *pixels, int npixels, void *closure)
1038 {
1039         if(colourmap != privateColourmap) XFreeColors(display, colourmap, pixels, npixels, 0);
1040         return(1); /* non-zero for success */
1041 }
1042
1043 #endif