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