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