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