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