rnd-20000917-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
569
570
571 /* +-----------------------------------------------------------------------+ */
572 /* | SDL TEST STUFF                                                        | */
573 /* +-----------------------------------------------------------------------+ */
574
575 #ifdef  USE_SDL_JOYSTICK
576
577 SDL_Surface *sdl_screen, *sdl_image_tmp, *sdl_image, *sdl_image_masked;
578 SDL_Surface *sdl_image2_tmp, *sdl_image2, *sdl_image2_masked;
579
580 void TEST_SDL_BLIT_RECT(int x, int y)
581 {
582   SDL_Rect rect_src, rect_dst;
583
584   SDLCopyArea(pix_masked[PIX_HEROES], window,
585               8 * TILEX, 8 * TILEY, TILEX, TILEY, x, y);
586   return;
587
588   rect_src.x = 8 * TILEX;
589   rect_src.y = 8 * TILEY;
590   rect_src.w = TILEX;
591   rect_src.h = TILEY;
592
593   rect_dst.x = x;
594   rect_dst.y = y;
595   rect_dst.w = TILEX;
596   rect_dst.h = TILEY;
597
598   SDL_BlitSurface(sdl_image2_masked, &rect_src, sdl_screen, &rect_dst);
599   SDL_UpdateRect(sdl_screen, x, y, TILEX, TILEY);
600 }
601
602 void TEST_SDL_INIT_DISPLAY()
603 {
604   SDL_Rect rect_src, rect_dst;
605
606   if (SDL_Init(SDL_INIT_VIDEO) < 0)
607   {
608     fprintf(stderr, "SDL_Init() failed: %s\n", SDL_GetError());
609     exit(1);
610   }
611
612   /* automatically cleanup SDL stuff after exit() */
613   atexit(SDL_Quit);
614
615   if ((sdl_screen = SDL_SetVideoMode(WIN_XSIZE, WIN_YSIZE, 16, SDL_HWSURFACE))
616       == NULL)
617   {
618     fprintf(stderr, "SDL_SetVideoMode() failed: %s\n", SDL_GetError());
619     exit(1);
620   }
621
622   SDL_WM_SetCaption(WINDOW_TITLE_STRING, WINDOW_TITLE_STRING);
623
624   if ((sdl_image_tmp = IMG_Load("graphics/RocksScreen.pcx")) == NULL)
625   {
626     fprintf(stderr, "IMG_Load() failed: %s\n", SDL_GetError());
627     exit(1);
628   }
629
630   sdl_image = SDL_DisplayFormat(sdl_image_tmp);
631
632   SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
633                   SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
634   sdl_image_masked = SDL_DisplayFormat(sdl_image_tmp);
635
636   SDL_FreeSurface(sdl_image_tmp);
637
638   if ((sdl_image2_tmp = IMG_Load("graphics/RocksHeroes.pcx")) == NULL)
639   {
640     fprintf(stderr, "IMG_Load() failed: %s\n", SDL_GetError());
641     exit(1);
642   }
643
644   sdl_image2 = SDL_DisplayFormat(sdl_image2_tmp);
645   SDL_FreeSurface(sdl_image2_tmp);
646
647   sdl_image2_masked = SDL_DisplayFormat(sdl_image2);
648   SDL_SetColorKey(sdl_image2_masked, SDL_SRCCOLORKEY,
649                   SDL_MapRGB(sdl_image2_masked->format, 0x00, 0x00, 0x00));
650
651   rect_src.x = 0;
652   rect_src.y = 0;
653   rect_src.w = sdl_image->w;
654   rect_src.h = sdl_image->h;
655
656   rect_dst.x = 0;
657   rect_dst.y = 0;
658   rect_dst.w = sdl_image->w;
659   rect_dst.h = sdl_image->h;
660                                            
661   SDL_BlitSurface(sdl_image, &rect_src, sdl_screen, &rect_dst);
662
663   /*
664   SDL_UpdateRect(sdl_screen, 0, 0, WIN_XSIZE, WIN_YSIZE);
665   */
666   /*
667   SDL_UpdateRect(sdl_screen, 0, 0, 0, 0);
668   */
669   SDL_Flip(sdl_screen);
670
671   /*
672   SDL_Delay(5000);
673   */
674 }
675
676 void TEST_SDL_EVENT_LOOP()
677 {
678   int quit_loop = 0;
679
680   SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
681
682   /*
683   while (!quit_loop && SDL_WaitEvent(&event) >=0)
684   */
685
686   while (!quit_loop)
687   {
688     SDL_Event event;
689
690     if (SDL_PollEvent(&event))
691     {
692       /* hier werden die Ereignisse behandelt */
693       switch(event.type)
694       {
695         case SDL_QUIT:
696         {
697           quit_loop = 1;
698           break;
699         }
700
701         case SDL_MOUSEBUTTONDOWN:
702         {
703           int x = event.button.x;
704           int y = event.button.y;
705
706           SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);
707
708           TEST_SDL_BLIT_RECT(x, y);
709
710           printf("SDL_MOUSEBUTTONDOWN(%d, %d)\n", x, y);
711           break;
712         }
713
714         case SDL_MOUSEBUTTONUP:
715         {
716           int x = event.button.x;
717           int y = event.button.y;
718
719           SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
720
721           printf("SDL_MOUSEBUTTONUP(%d, %d)\n", x, y);
722           break;
723         }
724
725         case SDL_MOUSEMOTION:
726         {
727           int x = event.motion.x;
728           int y = event.motion.y;
729
730           TEST_SDL_BLIT_RECT(x, y);
731
732           printf("SDL_MOUSEMOTION(%d, %d)\n", x, y);
733           break;
734         }
735
736         default:
737           break;
738       }
739     }
740
741     if (!SDL_PollEvent(NULL))   /* delay only if no pending events */
742     {
743       printf("waiting...\n");
744       Delay(100);
745     }
746   }
747
748   SDL_FreeSurface(sdl_image);
749   SDL_Quit();
750 }
751
752 #define SCREEN_WIDTH    640
753 #define SCREEN_HEIGHT   480
754
755 void WatchJoysticks()
756 {
757         SDL_Surface *screen;
758         const char *name;
759         int i, done;
760         SDL_Event event;
761         int x, y, draw;
762         SDL_Rect axis_area[2];
763         int joystick_nr = 0;
764         SDL_Joystick *joystick = Get_SDL_Joystick(joystick_nr);
765
766         /* Set a video mode to display joystick axis position */
767         screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 16, 0);
768         if ( screen == NULL ) {
769                 fprintf(stderr, "Couldn't set video mode: %s\n",SDL_GetError());
770                 return;
771         }
772
773         /* Print info about the joysticks we are watching */
774         for (i=0; i<2; i++)
775         {
776           joystick = Get_SDL_Joystick(i);
777
778           name = SDL_JoystickName(i);
779           printf("Watching joystick %d: (%s)\n", i,
780                  name ? name : "Unknown Joystick");
781           printf("Joystick has %d axes, %d hats, %d balls, and %d buttons\n",
782                  SDL_JoystickNumAxes(joystick),
783                  SDL_JoystickNumHats(joystick),
784                  SDL_JoystickNumBalls(joystick),
785                  SDL_JoystickNumButtons(joystick));
786         }
787
788         /* Initialize drawing rectangles */
789         memset(axis_area, 0, (sizeof axis_area));
790         draw = 0;
791
792         /* Loop, getting joystick events! */
793         done = 0;
794         while ( ! done ) {
795                 while ( SDL_PollEvent(&event) ) {
796                         switch (event.type) {
797                             case SDL_JOYAXISMOTION:
798                               joystick_nr = event.jaxis.which;
799                                 printf("Joystick %d axis %d value: %d\n",
800                                        event.jaxis.which,
801                                        event.jaxis.axis,
802                                        event.jaxis.value);
803                                 break;
804                             case SDL_JOYHATMOTION:
805                               joystick_nr = event.jaxis.which;
806                                 printf("Joystick %d hat %d value:",
807                                        event.jhat.which,
808                                        event.jhat.hat);
809                                 if ( event.jhat.value == SDL_HAT_CENTERED )
810                                         printf(" centered");
811                                 if ( event.jhat.value & SDL_HAT_UP )
812                                         printf(" up");
813                                 if ( event.jhat.value & SDL_HAT_RIGHT )
814                                         printf(" right");
815                                 if ( event.jhat.value & SDL_HAT_DOWN )
816                                         printf(" down");
817                                 if ( event.jhat.value & SDL_HAT_LEFT )
818                                         printf(" left");
819                                 printf("\n");
820                                 break;
821                             case SDL_JOYBALLMOTION:
822                               joystick_nr = event.jaxis.which;
823                                 printf("Joystick %d ball %d delta: (%d,%d)\n",
824                                        event.jball.which,
825                                        event.jball.ball,
826                                        event.jball.xrel,
827                                        event.jball.yrel);
828                                 break;
829                             case SDL_JOYBUTTONDOWN:
830                               joystick_nr = event.jaxis.which;
831                                 printf("Joystick %d button %d down\n",
832                                        event.jbutton.which,
833                                        event.jbutton.button);
834                                 break;
835                             case SDL_JOYBUTTONUP:
836                               joystick_nr = event.jaxis.which;
837                                 printf("Joystick %d button %d up\n",
838                                        event.jbutton.which,
839                                        event.jbutton.button);
840                                 break;
841                             case SDL_KEYDOWN:
842                                 if ( event.key.keysym.sym != SDLK_ESCAPE ) {
843                                         break;
844                                 }
845                                 /* Fall through to signal quit */
846                             case SDL_QUIT:
847                                 done = 1;
848                                 break;
849                             default:
850                                 break;
851                         }
852                 }
853
854                 joystick = Get_SDL_Joystick(joystick_nr);               
855
856                 /* Update visual joystick state */
857                 for ( i=0; i<SDL_JoystickNumButtons(joystick); ++i ) {
858                         SDL_Rect area;
859
860                         area.x = i*34;
861                         area.y = SCREEN_HEIGHT-34;
862                         area.w = 32;
863                         area.h = 32;
864                         if (SDL_JoystickGetButton(joystick, i) == SDL_PRESSED) {
865                                 SDL_FillRect(screen, &area, 0xFFFF);
866                         } else {
867                                 SDL_FillRect(screen, &area, 0x0000);
868                         }
869                         SDL_UpdateRects(screen, 1, &area);
870                 }
871
872                 /* Erase previous axes */
873                 SDL_FillRect(screen, &axis_area[draw], 0x0000);
874
875                 /* Draw the X/Y axis */
876                 draw = !draw;
877                 x = (((int)SDL_JoystickGetAxis(joystick, 0))+32768);
878                 x *= SCREEN_WIDTH;
879                 x /= 65535;
880                 if ( x < 0 ) {
881                         x = 0;
882                 } else
883                 if ( x > (SCREEN_WIDTH-16) ) {
884                         x = SCREEN_WIDTH-16;
885                 }
886                 y = (((int)SDL_JoystickGetAxis(joystick, 1))+32768);
887                 y *= SCREEN_HEIGHT;
888                 y /= 65535;
889                 if ( y < 0 ) {
890                         y = 0;
891                 } else
892                 if ( y > (SCREEN_HEIGHT-16) ) {
893                         y = SCREEN_HEIGHT-16;
894                 }
895                 axis_area[draw].x = (Sint16)x;
896                 axis_area[draw].y = (Sint16)y;
897                 axis_area[draw].w = 16;
898                 axis_area[draw].h = 16;
899                 SDL_FillRect(screen, &axis_area[draw], 0xFFFF);
900
901                 SDL_UpdateRects(screen, 2, axis_area);
902         }
903 }
904
905 void TEST_SDL_JOYSTICK()
906 {
907   const char *name;
908   int i;
909
910   /* Initialize SDL (Note: video is required to start event loop) */
911   if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_JOYSTICK) < 0 )
912   {
913     fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
914     exit(1);
915   }
916
917   /* Print information about the joysticks */
918   printf("There are %d joysticks attached\n", SDL_NumJoysticks());
919   for ( i=0; i<SDL_NumJoysticks(); ++i )
920   {
921     name = SDL_JoystickName(i);
922     printf("Joystick %d: %s\n",i,name ? name : "Unknown Joystick");
923   }
924
925   for (i=0; i<2; i++)
926   {
927     if (!Open_SDL_Joystick(i))
928       printf("Couldn't open joystick %d: %s\n", i, SDL_GetError());
929   }
930
931   WatchJoysticks();
932
933   for (i=0; i<2; i++)
934     Close_SDL_Joystick(i);
935
936   SDL_QuitSubSystem(SDL_INIT_VIDEO|SDL_INIT_JOYSTICK);
937 }
938
939 #endif  /* USE_SDL_JOYSTICK */
940
941 /* +-----------------------------------------------------------------------+ */
942 /* | SDL TEST STUFF                                                        | */
943 /* +-----------------------------------------------------------------------+ */
944
945
946
947 int main(int argc, char *argv[])
948 {
949   program_name = (strrchr(argv[0],'/') ? strrchr(argv[0],'/') + 1 : argv[0]);
950
951 #ifdef MSDOS
952   _fmode = O_BINARY;
953 #endif
954
955 #if 1
956   GetOptions(argv);
957   OpenAll(argc,argv);
958 #endif
959
960 #if 0
961 #ifdef USE_SDL_JOYSTICK
962   /*
963   TEST_SDL_BLIT_RECT((WIN_XSIZE - TILEX)/2, (WIN_YSIZE - TILEY)/2);
964   TEST_SDL_EVENT_LOOP();
965   */
966   TEST_SDL_JOYSTICK();
967   exit(0);
968 #endif
969 #endif
970
971   EventLoop();
972   CloseAllAndExit(0);
973   exit(0);      /* to keep compilers happy */
974 }