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