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