bf7e3f5bcba90a439112bc038f705e0bf57495c7
[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 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 #if 0
606
607 /* +-----------------------------------------------------------------------+ */
608 /* | SDL TEST STUFF                                                        | */
609 /* +-----------------------------------------------------------------------+ */
610
611 #if defined(TARGET_SDL)
612
613 SDL_Surface *sdl_screen, *sdl_image_tmp, *sdl_image, *sdl_image_masked;
614 SDL_Surface *sdl_image2_tmp, *sdl_image2, *sdl_image2_masked;
615
616 void TEST_SDL_BLIT_RECT(int x, int y)
617 {
618   SDL_Rect rect_src, rect_dst;
619
620   SDLCopyArea(pix_masked[PIX_HEROES], window,
621               8 * TILEX, 8 * TILEY, TILEX, TILEY, x, y);
622   return;
623
624   rect_src.x = 8 * TILEX;
625   rect_src.y = 8 * TILEY;
626   rect_src.w = TILEX;
627   rect_src.h = TILEY;
628
629   rect_dst.x = x;
630   rect_dst.y = y;
631   rect_dst.w = TILEX;
632   rect_dst.h = TILEY;
633
634   SDL_BlitSurface(sdl_image2_masked, &rect_src, sdl_screen, &rect_dst);
635   SDL_UpdateRect(sdl_screen, x, y, TILEX, TILEY);
636 }
637
638 void TEST_SDL_INIT_DISPLAY()
639 {
640   SDL_Rect rect_src, rect_dst;
641
642   if (SDL_Init(SDL_INIT_VIDEO) < 0)
643   {
644     fprintf(stderr, "SDL_Init() failed: %s\n", SDL_GetError());
645     exit(1);
646   }
647
648   /* automatically cleanup SDL stuff after exit() */
649   atexit(SDL_Quit);
650
651   if ((sdl_screen = SDL_SetVideoMode(WIN_XSIZE, WIN_YSIZE, 16, SDL_HWSURFACE))
652       == NULL)
653   {
654     fprintf(stderr, "SDL_SetVideoMode() failed: %s\n", SDL_GetError());
655     exit(1);
656   }
657
658   SDL_WM_SetCaption(WINDOW_TITLE_STRING, WINDOW_TITLE_STRING);
659
660   if ((sdl_image_tmp = IMG_Load("graphics/RocksScreen.pcx")) == NULL)
661   {
662     fprintf(stderr, "IMG_Load() failed: %s\n", SDL_GetError());
663     exit(1);
664   }
665
666   sdl_image = SDL_DisplayFormat(sdl_image_tmp);
667
668   SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
669                   SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
670   sdl_image_masked = SDL_DisplayFormat(sdl_image_tmp);
671
672   SDL_FreeSurface(sdl_image_tmp);
673
674   if ((sdl_image2_tmp = IMG_Load("graphics/RocksHeroes.pcx")) == NULL)
675   {
676     fprintf(stderr, "IMG_Load() failed: %s\n", SDL_GetError());
677     exit(1);
678   }
679
680   sdl_image2 = SDL_DisplayFormat(sdl_image2_tmp);
681   SDL_FreeSurface(sdl_image2_tmp);
682
683   sdl_image2_masked = SDL_DisplayFormat(sdl_image2);
684   SDL_SetColorKey(sdl_image2_masked, SDL_SRCCOLORKEY,
685                   SDL_MapRGB(sdl_image2_masked->format, 0x00, 0x00, 0x00));
686
687   rect_src.x = 0;
688   rect_src.y = 0;
689   rect_src.w = sdl_image->w;
690   rect_src.h = sdl_image->h;
691
692   rect_dst.x = 0;
693   rect_dst.y = 0;
694   rect_dst.w = sdl_image->w;
695   rect_dst.h = sdl_image->h;
696                                            
697   SDL_BlitSurface(sdl_image, &rect_src, sdl_screen, &rect_dst);
698
699   /*
700   SDL_UpdateRect(sdl_screen, 0, 0, WIN_XSIZE, WIN_YSIZE);
701   */
702   /*
703   SDL_UpdateRect(sdl_screen, 0, 0, 0, 0);
704   */
705   SDL_Flip(sdl_screen);
706
707   /*
708   SDL_Delay(5000);
709   */
710 }
711
712 void TEST_SDL_EVENT_LOOP()
713 {
714   int quit_loop = 0;
715
716   SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
717
718   /*
719   while (!quit_loop && SDL_WaitEvent(&event) >=0)
720   */
721
722   while (!quit_loop)
723   {
724     SDL_Event event;
725
726     if (SDL_PollEvent(&event))
727     {
728       /* hier werden die Ereignisse behandelt */
729       switch(event.type)
730       {
731         case SDL_QUIT:
732         {
733           quit_loop = 1;
734           break;
735         }
736
737         case SDL_MOUSEBUTTONDOWN:
738         {
739           int x = event.button.x;
740           int y = event.button.y;
741
742           SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);
743
744           TEST_SDL_BLIT_RECT(x, y);
745
746           printf("SDL_MOUSEBUTTONDOWN(%d, %d)\n", x, y);
747           break;
748         }
749
750         case SDL_MOUSEBUTTONUP:
751         {
752           int x = event.button.x;
753           int y = event.button.y;
754
755           SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
756
757           printf("SDL_MOUSEBUTTONUP(%d, %d)\n", x, y);
758           break;
759         }
760
761         case SDL_MOUSEMOTION:
762         {
763           int x = event.motion.x;
764           int y = event.motion.y;
765
766           TEST_SDL_BLIT_RECT(x, y);
767
768           printf("SDL_MOUSEMOTION(%d, %d)\n", x, y);
769           break;
770         }
771
772         default:
773           break;
774       }
775     }
776
777     if (!SDL_PollEvent(NULL))   /* delay only if no pending events */
778     {
779       printf("waiting...\n");
780       Delay(100);
781     }
782   }
783
784   SDL_FreeSurface(sdl_image);
785   SDL_Quit();
786 }
787
788 #define SCREEN_WIDTH    640
789 #define SCREEN_HEIGHT   480
790
791 void WatchJoysticks()
792 {
793         SDL_Surface *screen;
794         const char *name;
795         int i, done;
796         SDL_Event event;
797         int x, y, draw;
798         SDL_Rect axis_area[2];
799         int joystick_nr = 0;
800         SDL_Joystick *joystick = Get_SDL_Joystick(joystick_nr);
801
802         /* Set a video mode to display joystick axis position */
803         screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 16, 0);
804         if ( screen == NULL ) {
805                 fprintf(stderr, "Couldn't set video mode: %s\n",SDL_GetError());
806                 return;
807         }
808
809         /* Print info about the joysticks we are watching */
810         for (i=0; i<2; i++)
811         {
812           joystick = Get_SDL_Joystick(i);
813
814           name = SDL_JoystickName(i);
815           printf("Watching joystick %d: (%s)\n", i,
816                  name ? name : "Unknown Joystick");
817           printf("Joystick has %d axes, %d hats, %d balls, and %d buttons\n",
818                  SDL_JoystickNumAxes(joystick),
819                  SDL_JoystickNumHats(joystick),
820                  SDL_JoystickNumBalls(joystick),
821                  SDL_JoystickNumButtons(joystick));
822         }
823
824         /* Initialize drawing rectangles */
825         memset(axis_area, 0, (sizeof axis_area));
826         draw = 0;
827
828         /* Loop, getting joystick events! */
829         done = 0;
830         while ( ! done ) {
831                 while ( SDL_PollEvent(&event) ) {
832                         switch (event.type) {
833                             case SDL_JOYAXISMOTION:
834                               joystick_nr = event.jaxis.which;
835                                 printf("Joystick %d axis %d value: %d\n",
836                                        event.jaxis.which,
837                                        event.jaxis.axis,
838                                        event.jaxis.value);
839                                 break;
840                             case SDL_JOYHATMOTION:
841                               joystick_nr = event.jaxis.which;
842                                 printf("Joystick %d hat %d value:",
843                                        event.jhat.which,
844                                        event.jhat.hat);
845                                 if ( event.jhat.value == SDL_HAT_CENTERED )
846                                         printf(" centered");
847                                 if ( event.jhat.value & SDL_HAT_UP )
848                                         printf(" up");
849                                 if ( event.jhat.value & SDL_HAT_RIGHT )
850                                         printf(" right");
851                                 if ( event.jhat.value & SDL_HAT_DOWN )
852                                         printf(" down");
853                                 if ( event.jhat.value & SDL_HAT_LEFT )
854                                         printf(" left");
855                                 printf("\n");
856                                 break;
857                             case SDL_JOYBALLMOTION:
858                               joystick_nr = event.jaxis.which;
859                                 printf("Joystick %d ball %d delta: (%d,%d)\n",
860                                        event.jball.which,
861                                        event.jball.ball,
862                                        event.jball.xrel,
863                                        event.jball.yrel);
864                                 break;
865                             case SDL_JOYBUTTONDOWN:
866                               joystick_nr = event.jaxis.which;
867                                 printf("Joystick %d button %d down\n",
868                                        event.jbutton.which,
869                                        event.jbutton.button);
870                                 break;
871                             case SDL_JOYBUTTONUP:
872                               joystick_nr = event.jaxis.which;
873                                 printf("Joystick %d button %d up\n",
874                                        event.jbutton.which,
875                                        event.jbutton.button);
876                                 break;
877                             case SDL_KEYDOWN:
878                                 if ( event.key.keysym.sym != SDLK_ESCAPE ) {
879                                         break;
880                                 }
881                                 /* Fall through to signal quit */
882                             case SDL_QUIT:
883                                 done = 1;
884                                 break;
885                             default:
886                                 break;
887                         }
888                 }
889
890                 joystick = Get_SDL_Joystick(joystick_nr);               
891
892                 /* Update visual joystick state */
893                 for ( i=0; i<SDL_JoystickNumButtons(joystick); ++i ) {
894                         SDL_Rect area;
895
896                         area.x = i*34;
897                         area.y = SCREEN_HEIGHT-34;
898                         area.w = 32;
899                         area.h = 32;
900                         if (SDL_JoystickGetButton(joystick, i) == SDL_PRESSED) {
901                                 SDL_FillRect(screen, &area, 0xFFFF);
902                         } else {
903                                 SDL_FillRect(screen, &area, 0x0000);
904                         }
905                         SDL_UpdateRects(screen, 1, &area);
906                 }
907
908                 /* Erase previous axes */
909                 SDL_FillRect(screen, &axis_area[draw], 0x0000);
910
911                 /* Draw the X/Y axis */
912                 draw = !draw;
913                 x = (((int)SDL_JoystickGetAxis(joystick, 0))+32768);
914                 x *= SCREEN_WIDTH;
915                 x /= 65535;
916                 if ( x < 0 ) {
917                         x = 0;
918                 } else
919                 if ( x > (SCREEN_WIDTH-16) ) {
920                         x = SCREEN_WIDTH-16;
921                 }
922                 y = (((int)SDL_JoystickGetAxis(joystick, 1))+32768);
923                 y *= SCREEN_HEIGHT;
924                 y /= 65535;
925                 if ( y < 0 ) {
926                         y = 0;
927                 } else
928                 if ( y > (SCREEN_HEIGHT-16) ) {
929                         y = SCREEN_HEIGHT-16;
930                 }
931                 axis_area[draw].x = (Sint16)x;
932                 axis_area[draw].y = (Sint16)y;
933                 axis_area[draw].w = 16;
934                 axis_area[draw].h = 16;
935                 SDL_FillRect(screen, &axis_area[draw], 0xFFFF);
936
937                 SDL_UpdateRects(screen, 2, axis_area);
938         }
939 }
940
941 void TEST_SDL_JOYSTICK()
942 {
943   const char *name;
944   int i;
945
946   /* Initialize SDL (Note: video is required to start event loop) */
947   if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_JOYSTICK) < 0 )
948   {
949     fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
950     exit(1);
951   }
952
953   /* Print information about the joysticks */
954   printf("There are %d joysticks attached\n", SDL_NumJoysticks());
955   for ( i=0; i<SDL_NumJoysticks(); ++i )
956   {
957     name = SDL_JoystickName(i);
958     printf("Joystick %d: %s\n",i,name ? name : "Unknown Joystick");
959   }
960
961   for (i=0; i<2; i++)
962   {
963     if (!Open_SDL_Joystick(i))
964       printf("Couldn't open joystick %d: %s\n", i, SDL_GetError());
965   }
966
967   WatchJoysticks();
968
969   for (i=0; i<2; i++)
970     Close_SDL_Joystick(i);
971
972   SDL_QuitSubSystem(SDL_INIT_VIDEO|SDL_INIT_JOYSTICK);
973 }
974
975 #endif  /* TARGET_SDL */
976
977 /* +-----------------------------------------------------------------------+ */
978 /* | SDL TEST STUFF                                                        | */
979 /* +-----------------------------------------------------------------------+ */
980
981 #endif
982
983
984
985 int main(int argc, char *argv[])
986 {
987   program_name = (strrchr(argv[0],'/') ? strrchr(argv[0],'/') + 1 : argv[0]);
988
989 #if defined(PLATFORM_MSDOS)
990   _fmode = O_BINARY;
991 #endif
992
993 #if 1
994   GetOptions(argv);
995   OpenAll(argc,argv);
996 #endif
997
998 #if 0
999 #ifdef TARGET_SDL
1000   /*
1001   TEST_SDL_BLIT_RECT((WIN_XSIZE - TILEX)/2, (WIN_YSIZE - TILEY)/2);
1002   TEST_SDL_EVENT_LOOP();
1003   */
1004   TEST_SDL_JOYSTICK();
1005   exit(0);
1006 #endif
1007 #endif
1008
1009   EventLoop();
1010   CloseAllAndExit(0);
1011   exit(0);      /* to keep compilers happy */
1012 }