1 /* XDigger Copyright (C) 1988-99 Alexander Lang.
2
3 XDigger is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 XDigger is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; see the file COPYING. If not, write to
15 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
16
17 #include <fcntl.h>
18 #include <unistd.h>
19 #include <signal.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/time.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26
27 #include <X11/Xatom.h>
28 #include <X11/Xlib.h>
29 #include <X11/Xutil.h>
30
31 #include "configure.h"
32 #include "drawpixmaps.h"
33 #include "drawtext.h"
34 #include "highscore.h"
35 #include "icon.h"
36 #include "runlevels.h"
37 #include "title.h"
38 #include "sound.h"
39 #include "xdigger.h"
40
41 char *level_filename = NULL;
42 int pargc;
43 char **pargv;
44 char progname[256];
45 char *LastArgv = NULL; /* end of argv */
46 char *display_name = NULL;
47
48 Atom protocol[1];
49 Display *display;
50 int screen;
51 Window rootwindow, mainwindow, toolswindow = 0;
52 GC gc;
53 XStandardColormap xstandardcolormap;
54 Colormap colormap;
55 int kcf_tuerkis, kcf_gelb, kcf_weiss, kcb_blau, kcb_rot, kcb_tuerkis;
56 int xpmmag = 2, iconmag = 3;
57 Bool vert240 = False;
58 Bool laszlo = False; /* especially for Laszlo (Hi Laszlo!) */
59 int vertvar;
60 Bool iconmove = True;
61 Bool blink = True;
62 Bool use_standardcolor = False;
63 struct itimerval timervalue = {{0, 0},{0, TAKT_LENGTH}};
64 Bool takt = False, icontakt = False;
65 /* Bool sigterm = False; */
66 Bool quit = False, back = False;
67 Bool in_xdigger_idle = False;
68 Bool debug = False;
69
70 static int signal_list[] = {SIGINT, SIGQUIT, SIGILL, SIGTERM,
71 SIGSEGV, 0};
72
73 int zaehler;
74
all_done(int s)75 void all_done(int s)
76 {
77 sound_done();
78 if(s == 0)
79 {
80 }
81 else
82 {
83 switch (s)
84 {
85 case SIGILL:
86 case SIGSEGV:
87 /*fprintf(stderr, "Program received signal %d.\n", s);*/
88 psignal(s, progname);
89 }
90 }
91 exit(0);
92 }
93
ErrorHandler(Display * display,XErrorEvent * xerrorevent)94 int ErrorHandler(Display *display, XErrorEvent *xerrorevent)
95 {
96 char buffer[1024];
97
98 XGetErrorText(display, xerrorevent->error_code, buffer, sizeof(buffer));
99 fprintf(stderr, "%s: xlib: %s\n", progname, buffer);
100 return 0;
101 }
102
IOErrorHandler(Display * display)103 int IOErrorHandler(Display *display)
104 {
105 fprintf(stderr, "%s: connection to X server lost.\n", progname);
106 all_done(0);
107 return 0;
108 }
109
TimerHandler()110 void TimerHandler()
111 {
112 takt = True;
113 signal(SIGALRM, &TimerHandler);
114
115 if (!in_runlevels || in_LevelEditor)
116 setitimer(ITIMER_REAL, &timervalue ,0);
117
118 if (++zaehler == STEP_MAX) zaehler = 0;
119 /*if ((zaehler == 1) && iconmove && (!in_handle_icon)) Handle_Icon();*/
120 if (zaehler == 1) icontakt = True;
121 } /* TimerHandler() */
122
My_USleep(unsigned long usec)123 int My_USleep(unsigned long usec)
124 {
125 fd_set readfds, wrfds, exfds;
126 struct timeval timeout;
127 unsigned long mask;
128 int nfds, nfound;
129
130 nfds = ConnectionNumber(display);
131 mask = (1 << nfds);
132
133 readfds.fds_bits[0] = mask;
134 wrfds.fds_bits[0] = exfds.fds_bits[0] = 0;
135
136 timeout.tv_sec = 0;
137 timeout.tv_usec = usec;
138 nfound = select(nfds, &readfds, &wrfds, &exfds, &timeout);
139 return(nfound);
140 } /* int My_USleep(unsigned long usec) */
141
XDigger_Idle()142 void XDigger_Idle()
143 {
144 in_xdigger_idle = True;
145 My_USleep(1000);
146 if (icontakt)
147 {
148 icontakt = False;
149 if (iconmove && (!in_handle_icon)) Handle_Icon();
150 }
151 in_xdigger_idle = False;
152 } /* void XDigger_Idle() */
153
MyRand(int rand_max)154 int MyRand(int rand_max)
155 {
156 int i;
157
158 i = rand() % rand_max;
159 /* i = ((rand() / RAND_MAX) * rand_max) */
160 return (i);
161 } /* int MyRand(int rand_max) */
162
File_Exists(char * filename)163 Bool File_Exists(char *filename)
164 {
165 FILE *f;
166
167 if ((f = fopen(filename, "r")) == NULL) return False;
168 fclose(f);
169 return True;
170 }
171
Determine_Level_Filename()172 Bool Determine_Level_Filename()
173 {
174 FILE *f;
175
176 if (level_filename == NULL)
177 {
178 level_filename = malloc(256);
179 strcat(strcpy(level_filename, XDIGGER_LIB_DIR), "/xdigger.level");
180 if ((f = fopen(level_filename, "r")) == NULL)
181 {
182 fprintf(stderr, "%s: can't open %s\n", progname, level_filename);
183 strcpy(level_filename, progname); strcat(level_filename, ".level");
184 fprintf(stderr, "%s: try %s... ", progname, level_filename);
185 if ((f = fopen(level_filename, "r")) == NULL)
186 {
187 fprintf(stderr, "failed.\n");
188 return(False);
189 }
190 else fprintf(stderr, "ok.\n");
191 }
192 }
193 else
194 {
195 if ((f = fopen(level_filename, "r")) == NULL)
196 {
197 fprintf(stderr, "%s: can't open %s\n", progname, level_filename);
198 return(False);
199 }
200 }
201 fclose(f);
202 return(True);
203 }
204
MakeWindow(int argc,char ** argv)205 void MakeWindow(int argc, char **argv)
206 {
207 XSizeHints main_win_sizehints;
208 XClassHint classhint;
209 int main_win_width, main_win_height;
210 /* XSetWindowAttributes winattr; */
211 /* int i; */
212
213 main_win_width = 320 * xpmmag;
214 main_win_height = (240 + vertvar*16) * xpmmag;
215
216 display = XOpenDisplay(display_name);
217 if (display == NULL)
218 {
219 if(display_name == NULL)
220 fprintf(stderr, "%s: can't open display (null)\n", progname);
221 else
222 fprintf(stderr, "%s: can't open display %s\n", progname, display_name);
223 exit(1);
224 }
225 screen = DefaultScreen(display);
226
227 rootwindow = DefaultRootWindow(display);
228 mainwindow = XCreateSimpleWindow(display, rootwindow, 0, 0,
229 main_win_width, main_win_height,
230 border_width,
231 WhitePixel(display, screen),
232 BlackPixel(display, screen));
233
234 main_win_sizehints.width = main_win_width;
235 main_win_sizehints.height = main_win_height;
236 main_win_sizehints.min_width = 320; /*main_win_width;*/
237 main_win_sizehints.min_height = (240 + vertvar*16); /*main_win_height;*/
238 /*main_win_sizehints.max_width = main_win_width;*/
239 /*main_win_sizehints.max_height = main_win_height;*/
240 main_win_sizehints.width_inc = 320;
241 main_win_sizehints.height_inc = (240 + vertvar*16);
242 main_win_sizehints.min_aspect.x = 20;
243 main_win_sizehints.min_aspect.y = (15 + vertvar);
244 main_win_sizehints.max_aspect.x = main_win_sizehints.min_aspect.x;
245 main_win_sizehints.max_aspect.y = main_win_sizehints.min_aspect.y;
246 main_win_sizehints.flags = PSize | PMinSize /*| PMaxSize*/ | PResizeInc | PAspect;
247
248 XSetStandardProperties(display, mainwindow, main_win_title, main_win_title,
249 None, argv, argc, &main_win_sizehints);
250 /*XSetWMNormalHints(display, mainwindow, &main_win_sizehints);*/
251 /*winattr.colormap = xstdclrmap.colormap;*/
252 /*XChangeWindowAttributes(display, mainwindow, CWColormap, &winattr);*/
253 classhint.res_name = "xdigger";
254 classhint.res_class = "XDigger";
255 XSetClassHint(display, mainwindow, &classhint);
256 } /* MakeWindow(int argc, char **argv) */
257
MakeColorsAndGCs()258 void MakeColorsAndGCs()
259 {
260 XGCValues gcvalues;
261 unsigned long gcvaluemask;
262 XColor color;
263 /* Status status; */
264 /* int count; */
265
266 /* status = XGetStandardColormap(display, rootwindow, &xstandardcolormap, */
267 /* XA_RGB_DEFAULT_MAP); */
268 /* xstandardcolormap = XAllocStandardColormap(); */
269 /* xstandardcolormap = NULL; */
270 /* count = 1; */
271 /* status = XGetRGBColormaps(display, mainwindow, &xstandardcolormap, &count, */
272 /* XA_RGB_COLOR_MAP); */
273 /* if (status == 0) */
274 /* fprintf(stderr, "Can't get standard colormap."); */
275
276 colormap = DefaultColormap(display, screen);
277 XParseColor(display, colormap, KCF_TUERKIS, &color);
278 XAllocColor(display, colormap, &color);
279 kcf_tuerkis = color.pixel;
280 XParseColor(display, colormap, KCF_GELB, &color);
281 XAllocColor(display, colormap, &color);
282 kcf_gelb = color.pixel;
283 XParseColor(display, colormap, KCF_WEISS, &color);
284 XAllocColor(display, colormap, &color);
285 kcf_weiss = color.pixel;
286 XParseColor(display, colormap, KCB_BLAU, &color);
287 XAllocColor(display, colormap, &color);
288 kcb_blau = color.pixel;
289 XParseColor(display, colormap, KCB_ROT, &color);
290 XAllocColor(display, colormap, &color);
291 kcb_rot = color.pixel;
292 XParseColor(display, colormap, KCB_TUERKIS, &color);
293 XAllocColor(display, colormap, &color);
294 kcb_tuerkis = color.pixel;
295
296 gcvalues.foreground = WhitePixel(display, screen);
297 gcvalues.background = BlackPixel(display, screen);
298 gcvaluemask = GCForeground | GCBackground;
299 gc = XCreateGC(display, mainwindow, gcvaluemask, &gcvalues);
300
301 gc_text_values.foreground = 0;
302 gc_text_values.background = 0;
303 gc_text_mask = GCForeground | GCBackground;
304 gc_text = XCreateGC(display, mainwindow, gc_text_mask, &gc_text_values);
305 } /* MakeColorsAndGCs() */
306
create_audiofiles()307 void create_audiofiles()
308 {
309 int fd;
310
311 Fill_TonBuffer(TON_AUDIO_LOW, TON_AUDIO_HIGH, TON_AUDIO_RATE, True);
312
313 #ifdef __FreeBSD__
314 fd = open(XDIGGER_LIB_DIR "/diamond.au", O_CREAT | O_WRONLY);
315 #else
316 fd = open("audio/diamond.au", O_CREAT | O_WRONLY);
317 #endif
318 fchmod(fd, 0644);
319 write(fd, &ton_buffer[TON_DIAMANT], ton_laenge[TON_DIAMANT]+24);
320 close(fd);
321
322 #ifdef __FreeBSD__
323 fd = open(XDIGGER_LIB_DIR "/stone.au", O_CREAT | O_WRONLY);
324 #else
325 fd = open("audio/stone.au", O_CREAT | O_WRONLY);
326 #endif
327 fchmod(fd, 0644);
328 write(fd, &ton_buffer[TON_STEINE], ton_laenge[TON_STEINE]+24);
329 close(fd);
330
331 #ifdef __FreeBSD__
332 fd = open(XDIGGER_LIB_DIR "/step.au", O_CREAT | O_WRONLY);
333 #else
334 fd = open("audio/step.au", O_CREAT | O_WRONLY);
335 #endif
336 fchmod(fd, 0644);
337 write(fd, &ton_buffer[TON_SCHRITT], ton_laenge[TON_SCHRITT]+24);
338 close(fd);
339 exit(0);
340 }
341
Version()342 void Version()
343 {
344 printf("XDigger Version %s\n", VERSION);
345 exit(1);
346 } /* Version() */
347
Help()348 void Help()
349 {
350 printf("Usage: xdigger [-display display] [-1|2|3|...] [-noblink] [-noiconmove] [-vert240] [-sound ");
351 #ifdef SOUND_DSP_AUDIO
352 #if ( defined(linux) || defined(__FreeBSD__) )
353 printf("dsp|");
354 #endif
355 printf("audio|");
356 #endif
357 printf("xbell|");
358 #ifdef SOUND_RPLAY
359 printf("rplay|");
360 #endif
361 #ifdef SOUND_NAS
362 printf("nas|");
363 #endif
364 printf("auto|off] [-v] [-h]\n");
365 /*printf(" where n is a positive integer (default is 2)\n");*/
366 exit(1);
367 } /* Help() */
368
main(int argc,char ** argv)369 int main(int argc, char **argv)
370 {
371 int i, m = 0;
372 char c;
373 /*XWMHints wmhints;*/
374
375 pargc = argc;
376 pargv = argv;
377 strcpy(progname, argv[0]);
378 LastArgv = argv[argc - 1] + strlen(argv[argc - 1]);
379
380 for (i = 1; i < argc; i++)
381 {
382 if (!strcmp(argv[i], "-display")) display_name = argv[++i]; else
383 if ((!strcmp(argv[i], "-s")) ||
384 (!strcmp(argv[i], "-sound")) ||
385 (!strcmp(argv[i], "--sound")))
386 {
387 i++;
388 if(i == argc) Help();
389 if(!strcmp(argv[i], "auto")) sound_device = SD_AUTO; else
390 #ifdef SOUND_RPLAY
391 if(!strcmp(argv[i], "rplay")) sound_device = SD_RPLAY; else
392 #endif
393 if(!strcmp(argv[i], "nas"))
394 #ifdef SOUND_NAS
395 sound_device = SD_NAS; else
396 #else
397 {
398 fprintf(stderr, "%s: edit configure.h and recompile "
399 "xdigger for NAS-support\n", progname);
400 exit(1);
401 }
402 #endif
403 #ifdef SOUND_DSP_AUDIO
404 #if ( defined(linux) || defined(__FreeBSD__) )
405 if(!strcmp(argv[i], "dsp")) sound_device = SD_DSP; else
406 #endif
407 if(!strcmp(argv[i], "audio")) sound_device = SD_AUDIO; else
408 #endif
409 if(!strcmp(argv[i], "xbell")) sound_device = SD_XBELL; else
410 if(!strcmp(argv[i], "off") ||
411 !strcmp(argv[i], "none")) sound_device = SD_NONE; else Help();
412 } else
413 if (!strcmp(argv[i], "--nosound")) sound_device = SD_NONE; else
414 if (!strcmp(argv[i], "-iconmove") ||
415 !strcmp(argv[i], "--iconmove")) iconmove = True; else
416 if (!strcmp(argv[i], "-noiconmove") ||
417 !strcmp(argv[i], "--noiconmove")) iconmove = False; else
418 if (!strcmp(argv[i], "-standardcolor") ||
419 !strcmp(argv[i], "--standardcolor")) use_standardcolor = True; else
420 if (!strcmp(argv[i], "-vert240") ||
421 !strcmp(argv[i], "--vert240")) vert240 = True; else
422 if (!strcmp(argv[i], "-blink") ||
423 !strcmp(argv[i], "--blink")) blink = True; else
424 if (!strcmp(argv[i], "-noblink") ||
425 !strcmp(argv[i], "--noblink")) blink = False; else
426 if (!strcmp(argv[i], "--laszlo")) laszlo = True; else
427 if ( sscanf(argv[i], "-%d", &m) && (m > 0)) xpmmag = m; else
428 if (!strcmp(argv[i], "-v") ||
429 !strcmp(argv[i], "--version")) Version(); else
430 if (!strcmp(argv[i], "-?") ||
431 !strcmp(argv[i], "-h") ||
432 !strcmp(argv[i], "--help")) Help(); else
433 if (!strcmp(argv[i], "--create_audiofiles")) create_audiofiles(); else
434 if (!strcmp(argv[i], "-f") ||
435 !strcmp(argv[i], "-levelfilename") ||
436 !strcmp(argv[i], "--levelfilename"))
437 level_filename = strdup(argv[++i]); else
438 if (!strcmp(argv[i], "-d")) debug = True; else
439 if ((argv[i][0] != '-') && (File_Exists(argv[i])))
440 level_filename = strdup(argv[i]);
441 }
442
443 if (vert240) vertvar = 0; else vertvar = 1;
444 /*if (xpmmag != 2) iconmove = False;*/
445
446 if (!Determine_Level_Filename()) exit(1);
447
448 XSetErrorHandler(ErrorHandler);
449 XSetIOErrorHandler(IOErrorHandler);
450 MakeWindow(argc, argv);
451 MakeIconWindow();
452 MakeColorsAndGCs();
453 MakeXPixmaps(True);
454 ClearCharField(BlackPixel(display, screen), False);
455
456 /*wmhints.icon_pixmap = main_win_icon_pixmap;
457 wmhints.flags = IconPixmapHint;
458 XSetWMHints(display, mainwindow, &wmhints);*/
459
460 XSelectInput(display, mainwindow, ButtonPressMask | ButtonMotionMask |
461 KeyPressMask | KeyReleaseMask | ExposureMask);
462 XMapRaised(display, mainwindow);
463
464 protocol[0] = XInternAtom(display, "WM_DELETE_WINDOW", False);
465 XSetWMProtocols(display, mainwindow, protocol, 1);
466
467 sound_init();
468
469 /* Timer initialisieren & anstossen */
470 signal(SIGALRM, &TimerHandler);
471 {
472 int i;
473 for(i=0; signal_list[i] != 0; i++)
474 signal(signal_list[i], &all_done);
475 }
476 setitimer(ITIMER_REAL, &timervalue ,0);
477
478 while (!quit)
479 {
480 c = Title();
481 if (quit) break;
482 if (c == 'p')
483 {
484 RunLevels(1, -1);
485 if (quit) break;
486 if (!back) HighScore(score);
487 }
488 if (c == 'l')
489 {
490 ALookAtTheRooms();
491 if (quit) break;
492 }
493 if (c == 'e')
494 {
495 LevelEditor();
496 if (quit) break;
497 }
498 }
499 all_done(0);
500 return 0;
501 } /* main(int argc, char **argv) */
502