ec0a1c74a26369bf9e7361bc3b3c063552ce73a8
[rocksndiamonds.git] / src / init.c
1 /***********************************************************
2 *  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
3 *----------------------------------------------------------*
4 *  ©1995 Artsoft Development                               *
5 *        Holger Schemel                                    *
6 *        33659 Bielefeld-Senne                             *
7 *        Telefon: (0521) 493245                            *
8 *        eMail: aeglos@valinor.owl.de                      *
9 *               aeglos@uni-paderborn.de                    *
10 *               q99492@pbhrzx.uni-paderborn.de             *
11 *----------------------------------------------------------*
12 *  init.c                                                  *
13 *                                                          *
14 *  Letzte Aenderung: 15.06.1995                            *
15 ***********************************************************/
16
17 #include "init.h"
18 #include "images.h"
19 #include "sound.h"
20 #include "screens.h"
21 #include "tools.h"
22 #include "game.h"
23 #include "misc.h"
24
25 #include <signal.h>
26
27 int sound_process_id=0;
28
29 void OpenAll(int argc, char *argv[])
30 {
31   LoadLevelInfo();
32   LoadPlayerInfo(PLAYER_SETUP);
33   LoadPlayerInfo(PLAYER_LEVEL);
34
35   InitCounter();
36   InitSound();
37   InitSoundProcess();
38   InitJoystick();
39   InitRND(NEW_RANDOMIZE);
40
41   signal(SIGINT, CloseAll);
42   signal(SIGTERM, CloseAll);
43
44   InitDisplay(argc, argv);
45   InitWindow(argc, argv);
46   InitGfx();
47
48   DrawMainMenu();
49
50   XMapWindow(display, window);
51   XFlush(display);
52 }
53
54 void InitSound()
55 {
56   int i;
57
58   if (sound_status==SOUND_OFF)
59     return;
60
61   if (access(sound_device_name,W_OK)<0)
62   {
63     fprintf(stderr,"%s: cannot access sound device - no sounds\n",progname);
64     sound_status=SOUND_OFF;
65     return;
66   }
67
68   if ((sound_device=open(sound_device_name,O_WRONLY))<0)
69   {
70     fprintf(stderr,"%s: cannot open sound device - no sounds\n",progname);
71     sound_status=SOUND_OFF;
72     return;
73   }
74
75   close(sound_device);
76   sound_status=SOUND_AVAILABLE;
77
78 #ifdef VOXWARE
79   sound_loops_allowed = TRUE;
80   sound_loops_on = TRUE;
81 #endif
82
83   for(i=0;i<NUM_SOUNDS;i++)
84   {
85     Sound[i].name = sound_name[i];
86     if (!LoadSound(&Sound[i]))
87     {
88       sound_status=SOUND_OFF;
89       return;
90     }
91   }
92 }
93
94 void InitSoundProcess()
95 {
96   if (sound_status==SOUND_OFF)
97     return;
98
99   if (pipe(sound_pipe)<0)
100   {
101     fprintf(stderr,"%s: cannot create pipe - no sounds\n",progname);
102     sound_status=SOUND_OFF;
103     return;
104   }
105
106   if ((sound_process_id=fork())<0)
107   {       
108     fprintf(stderr,"%s: cannot create child process - no sounds\n",progname);
109     sound_status=SOUND_OFF;
110     return;
111   }
112
113   if (!sound_process_id)        /* we are child */
114     SoundServer();
115   else                          /* we are parent */
116     close(sound_pipe[0]);       /* no reading from pipe needed */
117 }
118
119 void InitJoystick()
120 {
121   if (global_joystick_status==JOYSTICK_OFF)
122     return;
123
124   if (access(joystick_device_name[joystick_nr],R_OK)<0)
125   {
126     fprintf(stderr,"%s: cannot access joystick device '%s'\n",
127             joystick_device_name[joystick_nr],progname);
128     joystick_status = JOYSTICK_OFF;
129     return;
130   }
131
132   if ((joystick_device=open(joystick_device_name[joystick_nr],O_RDONLY))<0)
133   {
134     fprintf(stderr,"%s: cannot open joystick device '%s'\n",
135             joystick_device_name[joystick_nr],progname);
136     joystick_status = JOYSTICK_OFF;
137     return;
138   }
139
140   joystick_status = JOYSTICK_AVAILABLE;
141   LoadJoystickData();
142 }
143
144 void InitDisplay(int argc, char *argv[])
145 {
146   char *display_name = NULL;
147   int i;
148
149   /* get X server to connect to, if given as an argument */
150   for (i=1;i<argc-1;i++)
151   {
152     char *dispstr="-display";
153     int len=MAX(strlen(dispstr),strlen(argv[i]));
154
155     if (len<4)
156       continue;
157     else if (!strncmp(argv[i],dispstr,len))
158     {
159       display_name=argv[i+1];
160       break;
161     }
162   }
163
164   /* connect to X server */
165   if (!(display=XOpenDisplay(display_name)))
166   {
167     fprintf(stderr,"%s: cannot connect to X server %s\n", 
168             progname, XDisplayName(display_name));
169     exit(-1);
170   }
171   
172   screen = DefaultScreen(display);
173   cmap   = DefaultColormap(display, screen);
174   pen_fg = WhitePixel(display,screen);
175   pen_bg = BlackPixel(display,screen);
176 }
177
178 void InitWindow(int argc, char *argv[])
179 {
180   unsigned int border_width = 4;
181   Pixmap icon_pixmap, iconmask_pixmap;
182   unsigned int icon_width,icon_height;
183   int icon_hot_x,icon_hot_y;
184   char icon_filename[256];
185   XSizeHints size_hints;
186   XWMHints wm_hints;
187   XClassHint class_hints;
188   XTextProperty windowName, iconName;
189   XGCValues gc_values;
190   unsigned long gc_valuemask;
191   char *window_name = "Rocks'n'Diamonds";
192   char *icon_name = "Rocks'n'Diamonds";
193   long window_event_mask;
194
195   width = WIN_XSIZE;
196   height = WIN_YSIZE;
197
198   window = XCreateSimpleWindow(display, RootWindow(display, screen),
199                             WIN_XPOS, WIN_YPOS, width, height, border_width,
200                             pen_fg, pen_bg);
201
202   sprintf(icon_filename,"%s/%s",GFX_PATH,icon_pic.picture_filename);
203   XReadBitmapFile(display,window,icon_filename,
204                   &icon_width,&icon_height,
205                   &icon_pixmap,&icon_hot_x,&icon_hot_y);
206   if (!icon_pixmap)
207   {
208     fprintf(stderr, "%s: cannot read icon bitmap file '%s'.\n",
209             progname,icon_filename);
210     exit(-1);
211   }
212
213   sprintf(icon_filename,"%s/%s",GFX_PATH,icon_pic.picturemask_filename);
214   XReadBitmapFile(display,window,icon_filename,
215                   &icon_width,&icon_height,
216                   &iconmask_pixmap,&icon_hot_x,&icon_hot_y);
217   if (!iconmask_pixmap)
218   {
219     fprintf(stderr, "%s: cannot read icon bitmap file '%s'.\n",
220             progname,icon_filename);
221     exit(-1);
222   }
223
224   size_hints.flags = PSize | PMinSize | PMaxSize;
225   size_hints.width  = size_hints.min_width  = size_hints.max_width  = width;
226   size_hints.height = size_hints.min_height = size_hints.max_height = height;
227
228   if (!XStringListToTextProperty(&window_name, 1, &windowName))
229   {
230     fprintf(stderr, "%s: structure allocation for windowName failed.\n",
231             progname);
232     exit(-1);
233   }
234
235   if (!XStringListToTextProperty(&icon_name, 1, &iconName))
236   {
237     fprintf(stderr, "%s: structure allocation for iconName failed.\n",
238             progname);
239     exit(-1);
240   }
241
242   wm_hints.initial_state = NormalState;
243   wm_hints.input = True;
244   wm_hints.icon_pixmap = icon_pixmap;
245   wm_hints.icon_mask = iconmask_pixmap;
246   wm_hints.flags = StateHint | IconPixmapHint | IconMaskHint | InputHint;
247
248   class_hints.res_name = progname;
249   class_hints.res_class = "Rocks'n'Diamonds";
250
251   XSetWMProperties(display, window, &windowName, &iconName, 
252                    argv, argc, &size_hints, &wm_hints, 
253                    &class_hints);
254
255   XFree(windowName.value);
256   XFree(iconName.value);
257
258   /* Select event types wanted */
259   window_event_mask = ExposureMask | StructureNotifyMask | FocusChangeMask |
260                       ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
261                       KeyPressMask | KeyReleaseMask;
262   XSelectInput(display, window, window_event_mask);
263
264   /* create GC for drawing with window depth */
265   gc_values.graphics_exposures = False;
266   gc_values.foreground = pen_bg;
267   gc_values.background = pen_bg;
268   gc_valuemask = GCGraphicsExposures | GCForeground | GCBackground;
269   gc = XCreateGC(display, window, gc_valuemask, &gc_values);
270 }
271
272 void InitGfx()
273 {
274   int i,j,x,y;
275   int xpm_err, xbm_err;
276   unsigned int width,height;
277   int hot_x,hot_y;
278   XGCValues gc_values;
279   unsigned long gc_valuemask;
280   XGCValues clip_gc_values;
281   unsigned long clip_gc_valuemask;
282   char filename[256];
283   Pixmap shapemask;
284
285   for(i=0;i<NUM_PICTURES;i++)
286   {
287     if (pic[i].picture_filename)
288     {
289       sprintf(filename,"%s/%s",GFX_PATH,pic[i].picture_filename);
290
291       xpm_att[i].valuemask = XpmCloseness;
292       xpm_att[i].closeness = 20000;
293       xpm_err = XpmReadFileToPixmap(display,window,filename,
294                                     &pix[i],&shapemask,&xpm_att[i]);
295       switch(xpm_err)
296       {
297         case XpmOpenFailed:
298           fprintf(stderr,"Xpm file open failed on '%s' !\n",filename);
299           CloseAll();
300           exit(-1);
301         case XpmFileInvalid:
302           fprintf(stderr,"Invalid Xpm file '%s'!\n",filename);
303           CloseAll();
304           exit(-1);
305         case XpmNoMemory:
306           fprintf(stderr,"Not enough memory !\n");      
307           CloseAll();
308           exit(1);
309         case XpmColorFailed:
310           fprintf(stderr,"Can`t get any colors...\n");
311           CloseAll();
312           exit(-1);
313         default:
314           break;
315       }
316       if (!pix[i])
317       {
318         fprintf(stderr, "%s: cannot read Xpm file '%s'.\n",
319                 progname,filename);
320         CloseAll();
321         exit(-1);
322       }
323     }
324
325     if (pic[i].picturemask_filename)
326     {
327       sprintf(filename,"%s/%s",GFX_PATH,pic[i].picturemask_filename);
328
329       xbm_err = XReadBitmapFile(display,window,filename,
330                                 &width,&height,&clipmask[i],&hot_x,&hot_y);
331       switch(xbm_err)
332       {
333         case BitmapSuccess:
334           break;
335         case BitmapOpenFailed:
336           fprintf(stderr,"Bitmap file open failed on '%s' !\n",filename);
337           CloseAll();
338           exit(-1);
339           break;
340         case BitmapFileInvalid:
341           fprintf(stderr,"Bitmap file invalid: '%s' !\n",filename);
342           CloseAll();
343           exit(-1);
344           break;
345         case BitmapNoMemory:
346           fprintf(stderr,"No memory for file '%s' !\n",filename);
347           CloseAll();
348           exit(-1);
349           break;
350         default:
351           break;
352       }
353       if (!clipmask[i])
354       {
355         fprintf(stderr, "%s: cannot read X11 bitmap file '%s'.\n",
356                 progname,filename);
357         CloseAll();
358         exit(-1);
359       }
360     }
361   }
362
363   pix[PIX_DB_BACK] = XCreatePixmap(display, window,
364                                    WIN_XSIZE,WIN_YSIZE,
365                                    XDefaultDepth(display,screen));
366   pix[PIX_DB_DOOR] = XCreatePixmap(display, window,
367                                    3*DXSIZE,DYSIZE+VYSIZE,
368                                    XDefaultDepth(display,screen));
369
370   clipmask[PIX_FADEMASK] = XCreatePixmap(display, window,
371                                          SXSIZE+TILEX,SYSIZE+TILEY,1);
372
373   if (!pix[PIX_DB_BACK] || !pix[PIX_DB_DOOR] || !clipmask[PIX_FADEMASK])
374   {
375     fprintf(stderr, "%s: cannot create additional Pixmaps!\n",progname);
376     CloseAll();
377     exit(-1);
378   }
379
380   /* create GC for drawing with bitplane depth */
381   gc_values.graphics_exposures = False;
382   gc_values.foreground = pen_bg;
383   gc_values.background = pen_bg;
384   gc_valuemask = GCGraphicsExposures | GCForeground | GCBackground;
385   plane_gc = XCreateGC(display, clipmask[PIX_BACK], gc_valuemask, &gc_values);
386
387   for(y=0;y<=SCR_FIELDY;y++) for(x=0;x<=SCR_FIELDX;x++)
388     XCopyArea(display,clipmask[PIX_BACK],clipmask[PIX_FADEMASK],plane_gc,
389               SX+2*TILEX,SY+10*TILEY,TILEX,TILEY,x*TILEX,y*TILEY);
390
391   for(i=0;i<NUM_PIXMAPS;i++)
392   {
393     if (clipmask[i])
394     {
395       clip_gc_values.graphics_exposures = False;
396       clip_gc_values.foreground = pen_fg;
397       clip_gc_values.background = pen_bg;
398       clip_gc_values.clip_mask = clipmask[i];
399       clip_gc_valuemask =
400         GCGraphicsExposures | GCForeground | GCBackground | GCClipMask;
401       clip_gc[i] = XCreateGC(display,window,clip_gc_valuemask,&clip_gc_values);
402     }
403   }
404
405   drawto = drawto_field = backbuffer = pix[PIX_DB_BACK];
406
407   XCopyArea(display,pix[PIX_BACK],backbuffer,gc,
408             0,0, WIN_XSIZE,WIN_YSIZE, 0,0);
409   XFillRectangle(display,backbuffer,gc,
410                  REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE);
411
412   for(i=0;i<SCR_FIELDX;i++)
413     for(j=0;j<SCR_FIELDY;j++)
414       redraw[i][j]=0;
415   redraw_tiles=0;
416   redraw_mask=REDRAW_ALL;
417 }
418
419 void CloseAll()
420 {
421   int i;
422
423   if (sound_process_id)
424   {
425     StopSounds();
426     kill(sound_process_id, SIGTERM);
427     FreeSounds(NUM_SOUNDS);
428   }
429
430   for(i=0;i<NUM_PIXMAPS;i++)
431   {
432     if (pix[i])
433     {
434       if (i<NUM_PICTURES)       /* XPM pictures */
435       {
436         XFreeColors(display,DefaultColormap(display,screen),
437                     xpm_att[i].pixels,xpm_att[i].npixels,0);
438         XpmFreeAttributes(&xpm_att[i]);
439       }
440       XFreePixmap(display,pix[i]);
441     }
442     if (clipmask[i])
443       XFreePixmap(display,clipmask[i]);
444     if (clip_gc[i])
445       XFreeGC(display, clip_gc[i]);
446   }
447
448   if (gc)
449     XFreeGC(display, gc);
450   if (plane_gc)
451     XFreeGC(display, plane_gc);
452
453   XCloseDisplay(display);
454
455   exit(0);
456 }