rnd-20001105-1-src
[rocksndiamonds.git] / src / main.c
1 /***********************************************************
2 *  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
3 *----------------------------------------------------------*
4 *  (c) 1995-98 Artsoft Entertainment                       *
5 *              Holger Schemel                              *
6 *              Oststrasse 11a                              *
7 *              33604 Bielefeld                             *
8 *              phone: ++49 +521 290471                     *
9 *              email: aeglos@valinor.owl.de                *
10 *----------------------------------------------------------*
11 *  main.c                                                  *
12 ***********************************************************/
13
14 #include "main.h"
15 #include "init.h"
16 #include "game.h"
17 #include "events.h"
18 #include "sound.h"
19 #include "joystick.h"
20 #include "misc.h"
21
22 #ifdef MSDOS
23 #include <fcntl.h>
24 #endif
25
26 Display        *display;
27 Visual         *visual;
28 int             screen;
29 DrawWindow      window = None;
30 GC              gc, clip_gc[NUM_BITMAPS], tile_clip_gc;
31 Bitmap          pix[NUM_BITMAPS];
32 Bitmap          pix_masked[NUM_BITMAPS], tile_masked[NUM_TILES];
33 Pixmap          clipmask[NUM_BITMAPS], tile_clipmask[NUM_TILES];
34
35 #ifdef USE_XPM_LIBRARY
36 XpmAttributes   xpm_att[NUM_PICTURES];
37 #endif
38
39 DrawBuffer      drawto, drawto_field, backbuffer, fieldbuffer;
40 Colormap        cmap;
41
42 int             sound_pipe[2];
43 int             sound_device;
44 char           *sound_device_name = SOUND_DEVICE;
45 int             joystick_device = 0;
46 char           *joystick_device_name[MAX_PLAYERS] =
47 {
48   DEV_JOYSTICK_0,
49   DEV_JOYSTICK_1,
50   DEV_JOYSTICK_2,
51   DEV_JOYSTICK_3
52 };
53
54 char           *program_name = NULL;
55
56 int             game_status = MAINMENU;
57 boolean         level_editor_test_game = FALSE;
58 boolean         network_playing = FALSE;
59 int             button_status = MB_NOT_PRESSED;
60 boolean         motion_status = FALSE;
61 int             key_joystick_mapping = 0;
62 int             global_joystick_status = JOYSTICK_STATUS;
63 int             joystick_status = JOYSTICK_STATUS;
64 int             sound_status = SOUND_STATUS;
65 boolean         sound_loops_allowed = FALSE;
66 boolean         fullscreen_available = FULLSCREEN_STATUS;
67 boolean         fullscreen_enabled = FALSE;
68
69 boolean         redraw[MAX_BUF_XSIZE][MAX_BUF_YSIZE];
70 int             redraw_x1 = 0, redraw_y1 = 0;
71 int             redraw_mask;
72 int             redraw_tiles;
73
74 short           Feld[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
75 short           Ur[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
76 short           MovPos[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
77 short           MovDir[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
78 short           MovDelay[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
79 short           Store[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
80 short           Store2[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
81 short           StorePlayer[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
82 short           Frame[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
83 boolean         Stop[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
84 short           JustStopped[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
85 short           AmoebaNr[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
86 short           AmoebaCnt[MAX_NUM_AMOEBA], AmoebaCnt2[MAX_NUM_AMOEBA];
87 unsigned long   Elementeigenschaften1[MAX_ELEMENTS];
88 unsigned long   Elementeigenschaften2[MAX_ELEMENTS];
89
90 int             level_nr;
91 int             lev_fieldx,lev_fieldy, scroll_x,scroll_y;
92
93 int             FX = SX, FY = SY, ScrollStepSize;
94 int             ScreenMovDir = MV_NO_MOVING, ScreenMovPos = 0;
95 int             ScreenGfxPos = 0;
96 int             BorderElement = EL_BETON;
97 int             GameFrameDelay = GAME_FRAME_DELAY;
98 int             FfwdFrameDelay = FFWD_FRAME_DELAY;
99 int             BX1 = 0, BY1 = 0, BX2 = SCR_FIELDX-1, BY2 = SCR_FIELDY-1;
100 int             SBX_Left, SBX_Right;
101 int             SBY_Upper, SBY_Lower;
102 int             ZX,ZY, ExitX,ExitY;
103 int             AllPlayersGone;
104 int             FrameCounter, TimeFrames, TimePlayed, TimeLeft;
105
106 boolean         network_player_action_received = FALSE;
107
108 struct LevelDirInfo    *leveldir_first = NULL, *leveldir_current = NULL;
109 struct LevelInfo        level;
110 struct PlayerInfo       stored_player[MAX_PLAYERS], *local_player = NULL;
111 struct HiScore          highscore[MAX_SCORE_ENTRIES];
112 struct SoundInfo        Sound[NUM_SOUNDS];
113 struct TapeInfo         tape;
114 struct OptionInfo       options;
115 struct SetupInfo        setup;
116 struct GameInfo         game;
117 struct GlobalInfo       global;
118
119 /* data needed for playing sounds */
120 char *sound_name[NUM_SOUNDS] =
121 {
122   "alchemy",
123   "amoebe",
124   "antigrav",
125   "autsch",
126   "blurb",
127   "bong",
128   "buing",
129   "chase",
130   "czardasz",
131   "deng",
132   "fuel",
133   "gong",
134   "halloffame",
135   "holz",
136   "hui",
137   "kabumm",
138   "kink",
139   "klapper",
140   "kling",
141   "klopf",
142   "klumpf",
143   "knack",
144   "knurk",
145   "krach",
146   "lachen",
147   "laser",
148   "miep",
149   "network",
150   "njam",
151   "oeffnen",
152   "pling",
153   "pong",
154   "pusch",
155   "quiek",
156   "quirk",
157   "rhythmloop",
158   "roaaar",
159   "roehr",
160   "rumms",
161   "schlopp",
162   "schlurf",
163   "schrff",
164   "schwirr",
165   "sirr",
166   "slurp",
167   "sproing",
168   "twilight",
169   "tyger",
170   "voyager",
171   "warnton",
172   "whoosh",
173   "zisch",
174   "base",
175   "infotron",
176   "zonkdown",
177   "zonkpush",
178   "bug",
179   "boom",
180   "booom",
181   "exit",
182   "empty",
183   "gate"
184 };
185
186 /* background music */
187 int background_loop[] =
188 {
189   SND_ALCHEMY,
190   SND_CHASE,
191   SND_NETWORK,
192   SND_CZARDASZ,
193   SND_TYGER,
194   SND_VOYAGER,
195   SND_TWILIGHT
196 };
197 int num_bg_loops = sizeof(background_loop)/sizeof(int);
198
199 char *element_info[] =
200 {
201   "empty space",                                /* 0 */
202   "sand",
203   "normal wall",
204   "round wall",
205   "rock",
206   "key",
207   "emerald",
208   "closed exit",
209   "player",
210   "bug",
211   "spaceship",                                  /* 10 */
212   "yam yam",
213   "robot",
214   "steel wall",
215   "diamond",
216   "dead amoeba",
217   "empty quicksand",
218   "quicksand with rock",
219   "amoeba drop",
220   "bomb",
221   "magic wall",                                 /* 20 */
222   "speed ball",
223   "acid pool",
224   "dropping amoeba",
225   "normal amoeba",
226   "nut with emerald",
227   "life wall",
228   "biomaze",
229   "burning dynamite",
230   "unknown",
231   "magic wheel",                                /* 30 */
232   "running wire",
233   "red key",
234   "yellow key",
235   "green key",
236   "blue key",
237   "red door",
238   "yellow door",
239   "green door",
240   "blue door",
241   "gray door (opened by red key)",              /* 40 */
242   "gray door (opened by yellow key)",
243   "gray door (opened by green key)",
244   "gray door (opened by blue key)",
245   "dynamite",
246   "pac man",
247   "invisible normal wall",
248   "light bulb (dark)",
249   "ligh bulb (glowing)",
250   "wall with emerald",
251   "wall with diamond",                          /* 50 */
252   "amoeba with content",
253   "amoeba (BD style)",
254   "time orb (full)",
255   "time orb (empty)",
256   "growing wall",
257   "diamond (BD style)",
258   "yellow emerald",
259   "wall with BD style diamond",
260   "wall with yellow emerald",
261   "dark yam yam",                               /* 60 */
262   "magic wall (BD style)",
263   "invisible steel wall",
264   "-",
265   "increases number of bombs",
266   "increases explosion size",
267   "increases power of explosion",
268   "sokoban object",
269   "sokoban empty field",
270   "sokoban field with object",
271   "butterfly (starts moving right)",            /* 70 */
272   "butterfly (starts moving up)",
273   "butterfly (starts moving left)",
274   "butterfly (starts moving down)",
275   "firefly (starts moving right)",
276   "firefly (starts moving up)",
277   "firefly (starts moving left)",
278   "firefly (starts moving down)",
279   "butterfly",
280   "firefly",
281   "yellow player",                              /* 80 */
282   "red player",
283   "green player",
284   "blue player",
285   "bug (starts moving right)",
286   "bug (starts moving up)",
287   "bug (starts moving left)",
288   "bug (starts moving down)",
289   "spaceship (starts moving right)",
290   "spaceship (starts moving up)",
291   "spaceship (starts moving left)",             /* 90 */
292   "spaceship (starts moving down)",
293   "pac man (starts moving right)",
294   "pac man (starts moving up)",
295   "pac man (starts moving left)",
296   "pac man (starts moving down)",
297   "red emerald",
298   "violet emerald",
299   "wall with red emerald",
300   "wall with violet emerald",
301   "unknown",                                    /* 100 */
302   "unknown",
303   "unknown",
304   "unknown",
305   "unknown",
306   "normal wall (BD style)",
307   "rock (BD style)",
308   "open exit",
309   "unknown",
310   "amoeba",
311   "mole",                                       /* 110 */
312   "penguin",
313   "satellite",
314   "arrow left",
315   "arrow right",
316   "arrow up",
317   "arrow down",
318   "pig",
319   "fire breathing dragon",
320   "unknown",
321   "letter ' '",                                 /* 120 */
322   "letter '!'",
323   "letter '\"'",
324   "letter '#'",
325   "letter '$'",
326   "letter '%'",
327   "letter '&'",
328   "letter '''",
329   "letter '('",
330   "letter ')'",
331   "letter '*'",                                 /* 130 */
332   "letter '+'",
333   "letter ','",
334   "letter '-'",
335   "letter '.'",
336   "letter '/'",
337   "letter '0'",
338   "letter '1'",
339   "letter '2'",
340   "letter '3'",
341   "letter '4'",                                 /* 140 */
342   "letter '5'",
343   "letter '6'",
344   "letter '7'",
345   "letter '8'",
346   "letter '9'",
347   "letter ':'",
348   "letter ';'",
349   "letter '<'",
350   "letter '='",
351   "letter '>'",                                 /* 150 */
352   "letter '?'",
353   "letter '@'",
354   "letter 'A'",
355   "letter 'B'",
356   "letter 'C'",
357   "letter 'D'",
358   "letter 'E'",
359   "letter 'F'",
360   "letter 'G'",
361   "letter 'H'",                                 /* 160 */
362   "letter 'I'",
363   "letter 'J'",
364   "letter 'K'",
365   "letter 'L'",
366   "letter 'M'",
367   "letter 'N'",
368   "letter 'O'",
369   "letter 'P'",
370   "letter 'Q'",
371   "letter 'R'",                                 /* 170 */
372   "letter 'S'",
373   "letter 'T'",
374   "letter 'U'",
375   "letter 'V'",
376   "letter 'W'",
377   "letter 'X'",
378   "letter 'Y'",
379   "letter 'Z'",
380   "letter 'Ä'",
381   "letter 'Ö'",                                 /* 180 */
382   "letter 'Ãœ'",
383   "letter '^'",
384   "letter ''",
385   "letter ''",
386   "letter ''",
387   "letter ''",
388   "letter ''",
389   "letter ''",
390   "letter ''",
391   "letter ''",                                  /* 190 */
392   "letter ''",
393   "letter ''",
394   "letter ''",
395   "letter ''",
396   "letter ''",
397   "letter ''",
398   "letter ''",
399   "letter ''",
400   "letter ''",
401   "growing wall (horizontal)",                  /* 200 */
402   "growing wall (vertical)",
403   "growing wall (all directions)",
404   "unused",
405   "unused",
406   "unused",
407   "unused",
408   "unused",
409   "unused",
410   "unused",
411   "empty space",                                /* 210 */
412   "zonk",
413   "base",
414   "murphy",
415   "infotron",
416   "chip (single)",
417   "hardware",
418   "exit",
419   "orange disk",
420   "port (leading right)",
421   "port (leading down)",                        /* 220 */
422   "port (leading left)",
423   "port (leading up)",
424   "port (leading right)",
425   "port (leading down)",
426   "port (leading left)",
427   "port (leading up)",
428   "snik snak",
429   "yellow disk",
430   "terminal",
431   "red disk",                                   /* 230 */
432   "port (vertical)",
433   "port (horizontal)",
434   "port (all directions)",
435   "electron",
436   "buggy base",
437   "chip (left half)",
438   "chip (right half)",
439   "hardware",
440   "hardware",
441   "hardware",                                   /* 240 */
442   "hardware",
443   "hardware",
444   "hardware",
445   "hardware",
446   "hardware",
447   "hardware",
448   "hardware",
449   "chip (upper half)",
450   "chip (lower half)",
451   "unknown",                                    /* 250 */
452   "unknown",
453   "unknown",
454   "unknown",
455   "unknown",
456   "unknown",
457
458   /* 256 */
459
460   "pearl",                                      /* (256) */
461   "crystal",
462   "wall with pearl",
463   "wall with crystal",
464   "white door",                                 /* 260 */
465   "gray door (opened by white key)",
466   "white key",
467   "shield (passive)",
468   "extra time",
469   "switch gate (open)",
470   "switch gate (closed)",
471   "switch for switch gate",
472   "switch for switch gate",
473   "-",
474   "-",                                          /* 270 */
475   "red conveyor belt (left)",
476   "red conveyor belt (middle)",
477   "red conveyor belt (right)",
478   "switch for red conveyor belt (left)",
479   "switch for red conveyor belt (middle)",
480   "switch for red conveyor belt (right)",
481   "yellow conveyor belt (left)",
482   "yellow conveyor belt (middle)",
483   "yellow conveyor belt (right)",
484   "switch for yellow conveyor belt (left)",     /* 280 */
485   "switch for yellow conveyor belt (middle)",
486   "switch for yellow conveyor belt (right)",
487   "green conveyor belt (left)",
488   "green conveyor belt (middle)",
489   "green conveyor belt (right)",
490   "switch for green conveyor belt (left)",
491   "switch for green conveyor belt (middle)",
492   "switch for green conveyor belt (right)",
493   "blue conveyor belt (left)",
494   "blue conveyor belt (middle)",                /* 290 */
495   "blue conveyor belt (right)",
496   "switch for blue conveyor belt (left)",
497   "switch for blue conveyor belt (middle)",
498   "switch for blue conveyor belt (right)",
499   "land mine",
500   "mail envelope",
501   "light switch (off)",
502   "light switch (on)",
503   "sign (exclamation)",
504   "sign (radio activity)",                      /* 300 */
505   "sign (stop)",
506   "sign (wheel chair)",
507   "sign (parking)",
508   "sign (one way)",
509   "sign (heart)",
510   "sign (triangle)",
511   "sign (round)",
512   "sign (exit)",
513   "sign (yin yang)",
514   "sign (other)",                               /* 310 */
515   "mole (starts moving left)",
516   "mole (starts moving right)",
517   "mole (starts moving up)",
518   "mole (starts moving down)",
519   "steel wall (slanted)",
520   "invisible sand",
521   "dx unknown 15",
522   "dx unknown 42",
523   "-",
524   "-",                                          /* 320 */
525   "shield (active, kills enemies)",
526   "time gate (open)",
527   "time gate (closed)",
528   "switch for time gate",
529   "switch for time gate",
530   "balloon",
531   "send balloon to the left",
532   "send balloon to the right",
533   "send balloon up",
534   "send balloon down",                          /* 330 */
535   "send balloon in any direction",
536   "steel wall",
537   "steel wall",
538   "steel wall",
539   "steel wall",
540   "normal wall",
541   "normal wall",
542   "normal wall",
543   "normal wall",
544   "normal wall",                                /* 340 */
545   "normal wall",
546   "normal wall",
547   "normal wall",
548   "tube (all directions)",
549   "tube (vertical)",
550   "tube (horizontal)",
551   "tube (vertical & left)",
552   "tube (vertical & right)",
553   "tube (horizontal & up)",
554   "tube (horizontal & down)",                   /* 350 */
555   "tube (left & up)",
556   "tube (left & down)",
557   "tube (right & up)",
558   "tube (right & down)",
559   "spring",
560   "trap",
561   "stable bomb (DX style)",
562   "-"
563
564   /*
565   "-------------------------------",
566   */
567 };
568 int num_element_info = sizeof(element_info)/sizeof(char *);
569
570
571
572 /* +-----------------------------------------------------------------------+ */
573 /* | SDL TEST STUFF                                                        | */
574 /* +-----------------------------------------------------------------------+ */
575
576 #ifdef  USE_SDL_JOYSTICK
577
578 SDL_Surface *sdl_screen, *sdl_image_tmp, *sdl_image, *sdl_image_masked;
579 SDL_Surface *sdl_image2_tmp, *sdl_image2, *sdl_image2_masked;
580
581 void TEST_SDL_BLIT_RECT(int x, int y)
582 {
583   SDL_Rect rect_src, rect_dst;
584
585   SDLCopyArea(pix_masked[PIX_HEROES], window,
586               8 * TILEX, 8 * TILEY, TILEX, TILEY, x, y);
587   return;
588
589   rect_src.x = 8 * TILEX;
590   rect_src.y = 8 * TILEY;
591   rect_src.w = TILEX;
592   rect_src.h = TILEY;
593
594   rect_dst.x = x;
595   rect_dst.y = y;
596   rect_dst.w = TILEX;
597   rect_dst.h = TILEY;
598
599   SDL_BlitSurface(sdl_image2_masked, &rect_src, sdl_screen, &rect_dst);
600   SDL_UpdateRect(sdl_screen, x, y, TILEX, TILEY);
601 }
602
603 void TEST_SDL_INIT_DISPLAY()
604 {
605   SDL_Rect rect_src, rect_dst;
606
607   if (SDL_Init(SDL_INIT_VIDEO) < 0)
608   {
609     fprintf(stderr, "SDL_Init() failed: %s\n", SDL_GetError());
610     exit(1);
611   }
612
613   /* automatically cleanup SDL stuff after exit() */
614   atexit(SDL_Quit);
615
616   if ((sdl_screen = SDL_SetVideoMode(WIN_XSIZE, WIN_YSIZE, 16, SDL_HWSURFACE))
617       == NULL)
618   {
619     fprintf(stderr, "SDL_SetVideoMode() failed: %s\n", SDL_GetError());
620     exit(1);
621   }
622
623   SDL_WM_SetCaption(WINDOW_TITLE_STRING, WINDOW_TITLE_STRING);
624
625   if ((sdl_image_tmp = IMG_Load("graphics/RocksScreen.pcx")) == NULL)
626   {
627     fprintf(stderr, "IMG_Load() failed: %s\n", SDL_GetError());
628     exit(1);
629   }
630
631   sdl_image = SDL_DisplayFormat(sdl_image_tmp);
632
633   SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
634                   SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
635   sdl_image_masked = SDL_DisplayFormat(sdl_image_tmp);
636
637   SDL_FreeSurface(sdl_image_tmp);
638
639   if ((sdl_image2_tmp = IMG_Load("graphics/RocksHeroes.pcx")) == NULL)
640   {
641     fprintf(stderr, "IMG_Load() failed: %s\n", SDL_GetError());
642     exit(1);
643   }
644
645   sdl_image2 = SDL_DisplayFormat(sdl_image2_tmp);
646   SDL_FreeSurface(sdl_image2_tmp);
647
648   sdl_image2_masked = SDL_DisplayFormat(sdl_image2);
649   SDL_SetColorKey(sdl_image2_masked, SDL_SRCCOLORKEY,
650                   SDL_MapRGB(sdl_image2_masked->format, 0x00, 0x00, 0x00));
651
652   rect_src.x = 0;
653   rect_src.y = 0;
654   rect_src.w = sdl_image->w;
655   rect_src.h = sdl_image->h;
656
657   rect_dst.x = 0;
658   rect_dst.y = 0;
659   rect_dst.w = sdl_image->w;
660   rect_dst.h = sdl_image->h;
661                                            
662   SDL_BlitSurface(sdl_image, &rect_src, sdl_screen, &rect_dst);
663
664   /*
665   SDL_UpdateRect(sdl_screen, 0, 0, WIN_XSIZE, WIN_YSIZE);
666   */
667   /*
668   SDL_UpdateRect(sdl_screen, 0, 0, 0, 0);
669   */
670   SDL_Flip(sdl_screen);
671
672   /*
673   SDL_Delay(5000);
674   */
675 }
676
677 void TEST_SDL_EVENT_LOOP()
678 {
679   int quit_loop = 0;
680
681   SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
682
683   /*
684   while (!quit_loop && SDL_WaitEvent(&event) >=0)
685   */
686
687   while (!quit_loop)
688   {
689     SDL_Event event;
690
691     if (SDL_PollEvent(&event))
692     {
693       /* hier werden die Ereignisse behandelt */
694       switch(event.type)
695       {
696         case SDL_QUIT:
697         {
698           quit_loop = 1;
699           break;
700         }
701
702         case SDL_MOUSEBUTTONDOWN:
703         {
704           int x = event.button.x;
705           int y = event.button.y;
706
707           SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);
708
709           TEST_SDL_BLIT_RECT(x, y);
710
711           printf("SDL_MOUSEBUTTONDOWN(%d, %d)\n", x, y);
712           break;
713         }
714
715         case SDL_MOUSEBUTTONUP:
716         {
717           int x = event.button.x;
718           int y = event.button.y;
719
720           SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
721
722           printf("SDL_MOUSEBUTTONUP(%d, %d)\n", x, y);
723           break;
724         }
725
726         case SDL_MOUSEMOTION:
727         {
728           int x = event.motion.x;
729           int y = event.motion.y;
730
731           TEST_SDL_BLIT_RECT(x, y);
732
733           printf("SDL_MOUSEMOTION(%d, %d)\n", x, y);
734           break;
735         }
736
737         default:
738           break;
739       }
740     }
741
742     if (!SDL_PollEvent(NULL))   /* delay only if no pending events */
743     {
744       printf("waiting...\n");
745       Delay(100);
746     }
747   }
748
749   SDL_FreeSurface(sdl_image);
750   SDL_Quit();
751 }
752
753 #define SCREEN_WIDTH    640
754 #define SCREEN_HEIGHT   480
755
756 void WatchJoysticks()
757 {
758         SDL_Surface *screen;
759         const char *name;
760         int i, done;
761         SDL_Event event;
762         int x, y, draw;
763         SDL_Rect axis_area[2];
764         int joystick_nr = 0;
765         SDL_Joystick *joystick = Get_SDL_Joystick(joystick_nr);
766
767         /* Set a video mode to display joystick axis position */
768         screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 16, 0);
769         if ( screen == NULL ) {
770                 fprintf(stderr, "Couldn't set video mode: %s\n",SDL_GetError());
771                 return;
772         }
773
774         /* Print info about the joysticks we are watching */
775         for (i=0; i<2; i++)
776         {
777           joystick = Get_SDL_Joystick(i);
778
779           name = SDL_JoystickName(i);
780           printf("Watching joystick %d: (%s)\n", i,
781                  name ? name : "Unknown Joystick");
782           printf("Joystick has %d axes, %d hats, %d balls, and %d buttons\n",
783                  SDL_JoystickNumAxes(joystick),
784                  SDL_JoystickNumHats(joystick),
785                  SDL_JoystickNumBalls(joystick),
786                  SDL_JoystickNumButtons(joystick));
787         }
788
789         /* Initialize drawing rectangles */
790         memset(axis_area, 0, (sizeof axis_area));
791         draw = 0;
792
793         /* Loop, getting joystick events! */
794         done = 0;
795         while ( ! done ) {
796                 while ( SDL_PollEvent(&event) ) {
797                         switch (event.type) {
798                             case SDL_JOYAXISMOTION:
799                               joystick_nr = event.jaxis.which;
800                                 printf("Joystick %d axis %d value: %d\n",
801                                        event.jaxis.which,
802                                        event.jaxis.axis,
803                                        event.jaxis.value);
804                                 break;
805                             case SDL_JOYHATMOTION:
806                               joystick_nr = event.jaxis.which;
807                                 printf("Joystick %d hat %d value:",
808                                        event.jhat.which,
809                                        event.jhat.hat);
810                                 if ( event.jhat.value == SDL_HAT_CENTERED )
811                                         printf(" centered");
812                                 if ( event.jhat.value & SDL_HAT_UP )
813                                         printf(" up");
814                                 if ( event.jhat.value & SDL_HAT_RIGHT )
815                                         printf(" right");
816                                 if ( event.jhat.value & SDL_HAT_DOWN )
817                                         printf(" down");
818                                 if ( event.jhat.value & SDL_HAT_LEFT )
819                                         printf(" left");
820                                 printf("\n");
821                                 break;
822                             case SDL_JOYBALLMOTION:
823                               joystick_nr = event.jaxis.which;
824                                 printf("Joystick %d ball %d delta: (%d,%d)\n",
825                                        event.jball.which,
826                                        event.jball.ball,
827                                        event.jball.xrel,
828                                        event.jball.yrel);
829                                 break;
830                             case SDL_JOYBUTTONDOWN:
831                               joystick_nr = event.jaxis.which;
832                                 printf("Joystick %d button %d down\n",
833                                        event.jbutton.which,
834                                        event.jbutton.button);
835                                 break;
836                             case SDL_JOYBUTTONUP:
837                               joystick_nr = event.jaxis.which;
838                                 printf("Joystick %d button %d up\n",
839                                        event.jbutton.which,
840                                        event.jbutton.button);
841                                 break;
842                             case SDL_KEYDOWN:
843                                 if ( event.key.keysym.sym != SDLK_ESCAPE ) {
844                                         break;
845                                 }
846                                 /* Fall through to signal quit */
847                             case SDL_QUIT:
848                                 done = 1;
849                                 break;
850                             default:
851                                 break;
852                         }
853                 }
854
855                 joystick = Get_SDL_Joystick(joystick_nr);               
856
857                 /* Update visual joystick state */
858                 for ( i=0; i<SDL_JoystickNumButtons(joystick); ++i ) {
859                         SDL_Rect area;
860
861                         area.x = i*34;
862                         area.y = SCREEN_HEIGHT-34;
863                         area.w = 32;
864                         area.h = 32;
865                         if (SDL_JoystickGetButton(joystick, i) == SDL_PRESSED) {
866                                 SDL_FillRect(screen, &area, 0xFFFF);
867                         } else {
868                                 SDL_FillRect(screen, &area, 0x0000);
869                         }
870                         SDL_UpdateRects(screen, 1, &area);
871                 }
872
873                 /* Erase previous axes */
874                 SDL_FillRect(screen, &axis_area[draw], 0x0000);
875
876                 /* Draw the X/Y axis */
877                 draw = !draw;
878                 x = (((int)SDL_JoystickGetAxis(joystick, 0))+32768);
879                 x *= SCREEN_WIDTH;
880                 x /= 65535;
881                 if ( x < 0 ) {
882                         x = 0;
883                 } else
884                 if ( x > (SCREEN_WIDTH-16) ) {
885                         x = SCREEN_WIDTH-16;
886                 }
887                 y = (((int)SDL_JoystickGetAxis(joystick, 1))+32768);
888                 y *= SCREEN_HEIGHT;
889                 y /= 65535;
890                 if ( y < 0 ) {
891                         y = 0;
892                 } else
893                 if ( y > (SCREEN_HEIGHT-16) ) {
894                         y = SCREEN_HEIGHT-16;
895                 }
896                 axis_area[draw].x = (Sint16)x;
897                 axis_area[draw].y = (Sint16)y;
898                 axis_area[draw].w = 16;
899                 axis_area[draw].h = 16;
900                 SDL_FillRect(screen, &axis_area[draw], 0xFFFF);
901
902                 SDL_UpdateRects(screen, 2, axis_area);
903         }
904 }
905
906 void TEST_SDL_JOYSTICK()
907 {
908   const char *name;
909   int i;
910
911   /* Initialize SDL (Note: video is required to start event loop) */
912   if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_JOYSTICK) < 0 )
913   {
914     fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
915     exit(1);
916   }
917
918   /* Print information about the joysticks */
919   printf("There are %d joysticks attached\n", SDL_NumJoysticks());
920   for ( i=0; i<SDL_NumJoysticks(); ++i )
921   {
922     name = SDL_JoystickName(i);
923     printf("Joystick %d: %s\n",i,name ? name : "Unknown Joystick");
924   }
925
926   for (i=0; i<2; i++)
927   {
928     if (!Open_SDL_Joystick(i))
929       printf("Couldn't open joystick %d: %s\n", i, SDL_GetError());
930   }
931
932   WatchJoysticks();
933
934   for (i=0; i<2; i++)
935     Close_SDL_Joystick(i);
936
937   SDL_QuitSubSystem(SDL_INIT_VIDEO|SDL_INIT_JOYSTICK);
938 }
939
940 #endif  /* USE_SDL_JOYSTICK */
941
942 /* +-----------------------------------------------------------------------+ */
943 /* | SDL TEST STUFF                                                        | */
944 /* +-----------------------------------------------------------------------+ */
945
946
947
948 int main(int argc, char *argv[])
949 {
950   program_name = (strrchr(argv[0],'/') ? strrchr(argv[0],'/') + 1 : argv[0]);
951
952 #ifdef MSDOS
953   _fmode = O_BINARY;
954 #endif
955
956 #if 1
957   GetOptions(argv);
958   OpenAll(argc,argv);
959 #endif
960
961 #if 0
962 #ifdef USE_SDL_JOYSTICK
963   /*
964   TEST_SDL_BLIT_RECT((WIN_XSIZE - TILEX)/2, (WIN_YSIZE - TILEY)/2);
965   TEST_SDL_EVENT_LOOP();
966   */
967   TEST_SDL_JOYSTICK();
968   exit(0);
969 #endif
970 #endif
971
972   EventLoop();
973   CloseAllAndExit(0);
974   exit(0);      /* to keep compilers happy */
975 }