f1dcfa473686ba19765dfae70497bd6021a702b9
[rocksndiamonds.git] / src / msdos.c
1 /***********************************************************
2 *  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
3 *----------------------------------------------------------*
4 *  ©1995 Artsoft Development                               *
5 *        Holger Schemel                                    *
6 *        33659 Bielefeld-Senne                             *
7 *        Telefon: (0521) 493245                            *
8 *        eMail: aeglos@valinor.owl.de                      *
9 *               aeglos@uni-paderborn.de                    *
10 *               q99492@pbhrzx.uni-paderborn.de             *
11 *----------------------------------------------------------*
12 *  msdos.c                                                 *
13 ***********************************************************/
14
15 #ifdef MSDOS
16
17 #include "main.h"
18 #include "tools.h"
19 #include "sound.h"
20 #include "files.h"
21 #include "joystick.h"
22 #include "image.h"
23
24 DECLARE_GFX_DRIVER_LIST(GFX_DRIVER_VBEAF GFX_DRIVER_VESA2L GFX_DRIVER_VESA1)
25 DECLARE_COLOR_DEPTH_LIST(COLOR_DEPTH_8)
26 DECLARE_DIGI_DRIVER_LIST(DIGI_DRIVER_SB)
27 DECLARE_MIDI_DRIVER_LIST()
28 DECLARE_JOYSTICK_DRIVER_LIST(JOYSTICK_DRIVER_STANDARD)
29
30 static int key_buffer[OSD_MAX_KEY];
31 static XEvent event_buffer[MAX_EVENT_BUFFER];
32 static int pending_events;
33 static boolean joystick_event;
34 static boolean mouse_installed = FALSE;
35 static int last_mouse_pos;
36 static int last_mouse_b;
37 static int last_joystick_state;
38 static BITMAP* video_bitmap;
39
40 static RGB global_colormap[MAX_COLORS];
41 static int global_colormap_entries_used = 0;
42
43 boolean wait_for_vsync;
44
45 extern int playing_sounds;
46 extern struct SoundControl playlist[MAX_SOUNDS_PLAYING];
47 extern struct SoundControl emptySoundControl;
48
49 static BITMAP *Read_PCX_to_AllegroBitmap(char *);
50
51 static void allegro_drivers()
52 {
53   int i;
54
55   for (i=0; i<MAX_EVENT_BUFFER; i++)
56     event_buffer[i].type = 0;
57   for(i=0; i<OSD_MAX_KEY; i++)
58     key_buffer[i] = KeyReleaseMask;
59   last_mouse_pos = mouse_pos;
60   last_mouse_b = 0;
61
62   pending_events = 0;
63   clear_keybuf();
64
65   i_love_bill = TRUE;
66   install_keyboard();
67   install_timer();
68   if (install_mouse() > 0)
69     mouse_installed = TRUE;
70   install_joystick(JOY_TYPE_2PADS);
71
72   load_joystick_data(JOYSTICK_FILENAME);
73   last_joystick_state = 0;
74   joystick_event = FALSE;
75
76   reserve_voices(MAX_SOUNDS_PLAYING, 0);
77   if (install_sound(DIGI_AUTODETECT, MIDI_NONE, "ROCKS.SND") == -1)
78     if (install_sound(DIGI_SB, MIDI_NONE, NULL) == -1)
79       sound_status = SOUND_OFF;
80 }
81
82 static boolean hide_mouse(Display *display, int x, int y,
83                           unsigned int width, unsigned int height)
84 {
85   if (mouse_x + display->mouse_ptr->w < x || mouse_x > x + width)
86     return FALSE;
87   if (mouse_y + display->mouse_ptr->h < y || mouse_y > y + height)
88     return FALSE;
89
90   show_mouse(NULL);
91
92   return TRUE;
93 }
94
95 static void unhide_mouse(Display *display)
96 {
97   if (mouse_installed)
98     show_mouse(video_bitmap);
99 }
100
101 static int get_joystick_state()
102 {
103   int state = 0;
104
105   /*!!!*/
106   int joystick_nr = 0;  /* CHANGE THIS! */
107   /*!!!*/
108
109   poll_joystick();
110
111   if (joy[joystick_nr].stick[0].axis[0].d1)
112     state |= JOY_LEFT;
113   if (joy[joystick_nr].stick[0].axis[0].d2)
114     state |= JOY_RIGHT;
115   if (joy[joystick_nr].stick[0].axis[1].d1)
116     state |= JOY_UP;
117   if (joy[joystick_nr].stick[0].axis[1].d2)
118     state |= JOY_DOWN;
119   if (joy[joystick_nr].button[0].b)
120     state |= JOY_BUTTON_1;
121
122   switch (state)
123   {
124     case (JOY_DOWN | JOY_LEFT):
125       state = XK_KP_1;
126       break;
127     case (JOY_DOWN):
128       state = XK_KP_2;
129       break;
130     case (JOY_DOWN | JOY_RIGHT):
131       state = XK_KP_3;
132       break;
133     case (JOY_LEFT):
134       state = XK_KP_4;
135       break;
136     case (JOY_RIGHT):
137       state = XK_KP_6;
138       break;
139     case (JOY_UP | JOY_LEFT):
140       state = XK_KP_7;
141       break;
142     case (JOY_UP):
143       state = XK_KP_8;
144       break;
145     case (JOY_UP | JOY_RIGHT):
146       state = XK_KP_9;
147       break;
148
149     case (JOY_DOWN | JOY_BUTTON_1):
150       state = XK_X;
151       break;
152     case (JOY_LEFT | JOY_BUTTON_1):
153       state = XK_S;
154       break;
155     case (JOY_RIGHT | JOY_BUTTON_1):
156       state = XK_D;
157       break;
158     case (JOY_UP | JOY_BUTTON_1):
159       state = XK_E;
160       break;
161  
162    default:
163      state = 0;
164   }
165
166   return state;
167 }
168
169 unsigned char get_ascii(KeySym key)
170 {
171   switch(key)
172   {
173     case OSD_KEY_Q: return 'Q';
174     case OSD_KEY_W: return 'W';
175     case OSD_KEY_E: return 'E';
176     case OSD_KEY_R: return 'R';
177     case OSD_KEY_T: return 'T';
178     case OSD_KEY_Y: return 'Y';
179     case OSD_KEY_U: return 'U';
180     case OSD_KEY_I: return 'I';
181     case OSD_KEY_O: return 'O';
182     case OSD_KEY_P: return 'P';
183     case OSD_KEY_A: return 'A';
184     case OSD_KEY_S: return 'S';
185     case OSD_KEY_D: return 'D';
186     case OSD_KEY_F: return 'F';
187     case OSD_KEY_G: return 'G';
188     case OSD_KEY_H: return 'H';
189     case OSD_KEY_J: return 'J';
190     case OSD_KEY_K: return 'K';
191     case OSD_KEY_L: return 'L';
192     case OSD_KEY_Z: return 'Z';
193     case OSD_KEY_X: return 'X';
194     case OSD_KEY_C: return 'C';
195     case OSD_KEY_V: return 'V';
196     case OSD_KEY_B: return 'B';
197     case OSD_KEY_N: return 'N';
198     case OSD_KEY_M: return 'M';
199     case OSD_KEY_1: return '1';
200     case OSD_KEY_2: return '2';
201     case OSD_KEY_3: return '3';
202     case OSD_KEY_4: return '4';
203     case OSD_KEY_5: return '5';
204     case OSD_KEY_6: return '6';
205     case OSD_KEY_7: return '7';
206     case OSD_KEY_8: return '8';
207     case OSD_KEY_9: return '9';
208     case OSD_KEY_0: return '0';
209     case OSD_KEY_SPACE: return ' ';
210   }
211
212   return 0;
213 }
214
215 static long osd_key_pressed(int keycode)
216 {
217   if (keycode == OSD_KEY_RCONTROL)
218     keycode = KEY_RCONTROL;
219   if (keycode == OSD_KEY_ALTGR)
220     keycode = KEY_ALTGR;
221
222   if (key[keycode])
223     return KeyPressMask;
224   else
225     return KeyReleaseMask;
226 }
227
228 void XMapWindow(Display *display, Window window)
229 {
230   int x, y;
231   unsigned int width, height;
232   boolean mouse_off;
233
234   x = display->screens[display->default_screen].x;
235   y = display->screens[display->default_screen].y;
236   width = display->screens[display->default_screen].width;
237   height = display->screens[display->default_screen].height;
238
239   mouse_off = hide_mouse(display, x, y, width, height);
240   blit((BITMAP *)window, video_bitmap, 0, 0, x, y, width, height);
241
242   if (mouse_off)
243     unhide_mouse(display);
244 }
245
246 Display *XOpenDisplay(char *display_name)
247 {
248   Screen *screen;
249   Display *display;
250   BITMAP *mouse_bitmap = NULL;
251
252   screen = malloc(sizeof(Screen));
253   display = malloc(sizeof(Display));
254
255   if ((mouse_bitmap = Read_PCX_to_AllegroBitmap(MOUSE_PCX_FILENAME)) == NULL)
256     return NULL;
257
258   screen[0].cmap = 0;
259   screen[0].root = 0;
260   screen[0].white_pixel = 0xFF;
261   screen[0].black_pixel = 0x00;
262   screen[0].video_bitmap = NULL;
263
264   display->default_screen = 0;
265   display->screens = screen;
266   display->mouse_ptr = mouse_bitmap;
267
268   allegro_init();
269   allegro_drivers();
270   set_color_depth(8);
271
272   /* force Windows 95 to switch to fullscreen mode */
273   set_gfx_mode(GFX_AUTODETECT, 320, 200, 0, 0);
274   rest(200);
275   set_gfx_mode(GFX_AUTODETECT, XRES, YRES, 0, 0);
276
277   return display;
278 }
279
280 Window XCreateSimpleWindow(Display *display, Window parent, int x, int y,
281                            unsigned int width, unsigned int height,
282                            unsigned int border_width, unsigned long border,
283                            unsigned long background)
284 {
285   video_bitmap = create_video_bitmap(XRES, YRES);
286   clear_to_color(video_bitmap, background);
287
288   display->screens[display->default_screen].video_bitmap = video_bitmap;
289   display->screens[display->default_screen].x = x;
290   display->screens[display->default_screen].y = y;
291   display->screens[display->default_screen].width = XRES;
292   display->screens[display->default_screen].height = YRES;
293
294   set_mouse_sprite(display->mouse_ptr);
295   set_mouse_range(display->screens[display->default_screen].x + 1,
296                   display->screens[display->default_screen].y + 1,
297                   display->screens[display->default_screen].x + WIN_XSIZE + 1,
298                   display->screens[display->default_screen].y + WIN_YSIZE + 1);
299
300   show_video_bitmap(video_bitmap);
301
302   return (Window)video_bitmap;
303 }
304
305 Status XStringListToTextProperty(char **list, int count,
306                                  XTextProperty *text_prop_return)
307 {
308   char *string;
309
310   if (count >= 1)
311   {
312     string = malloc(strlen(list[0] + 1));
313     strcpy(string, list[0]);
314     text_prop_return->value = (unsigned char *)string;
315     return 1;
316   }
317   else
318     text_prop_return = NULL;
319
320   return 0;
321 }
322
323 void XFree(void *data)
324 {
325   if (data)
326     free(data);
327 }
328
329 GC XCreateGC(Display *display, Drawable d, unsigned long value_mask,
330              XGCValues *values)
331 {
332   XGCValues *gcv;
333   gcv = malloc(sizeof(XGCValues));
334   gcv->foreground = values->foreground;
335   gcv->background = values->background;
336   gcv->graphics_exposures = values->graphics_exposures;
337   gcv->clip_mask = values->clip_mask;
338   gcv->clip_x_origin = values->clip_x_origin;
339   gcv->clip_y_origin = values->clip_y_origin;
340   gcv->value_mask = value_mask;
341   return (GC)gcv;
342 }
343
344 void XSetClipMask(Display *display, GC gc, Pixmap pixmap)
345 {
346   XGCValues *gcv = (XGCValues *)gc;
347
348   gcv->clip_mask = pixmap;
349   gcv->value_mask |= GCClipMask;
350 }
351
352 void XSetClipOrigin(Display *display, GC gc, int x, int y)
353 {
354   XGCValues *gcv = (XGCValues *)gc;
355
356   gcv->clip_x_origin = x;
357   gcv->clip_x_origin = y;
358 }
359
360 void XFillRectangle(Display *display, Drawable d, GC gc, int x, int y,
361                     unsigned int width, unsigned int height)
362 {
363   boolean mouse_off = FALSE;
364
365   if ((BITMAP *)d == video_bitmap)
366   {
367     x += display->screens[display->default_screen].x;
368     y += display->screens[display->default_screen].y;
369     freeze_mouse_flag = TRUE;
370     mouse_off = hide_mouse(display, x, y, width, height);
371   }
372
373   rectfill((BITMAP *)d, x, y, x + width, y + height,
374            ((XGCValues *)gc)->foreground);
375
376   if (mouse_off)
377     unhide_mouse(display);
378
379   freeze_mouse_flag = FALSE;
380 }
381
382 Pixmap XCreatePixmap(Display *display, Drawable d, unsigned int width,
383                      unsigned int height, unsigned int depth)
384 {
385   BITMAP *bitmap = NULL;
386
387   if (gfx_capabilities & GFX_HW_VRAM_BLIT &&
388       width == FXSIZE && height == FYSIZE)
389     bitmap = create_video_bitmap(width, height);
390
391   if (bitmap == NULL)
392     bitmap = create_bitmap(width, height);
393
394   return (Pixmap)bitmap;
395 }
396
397 void XSync(Display *display, Bool discard_events)
398 {
399   wait_for_vsync = TRUE;
400 }
401
402 inline void XCopyArea(Display *display, Drawable src, Drawable dest, GC gc,
403                       int src_x, int src_y,
404                       unsigned int width, unsigned int height,
405                       int dest_x, int dest_y)
406 {
407   boolean mouse_off = FALSE;
408
409   if ((BITMAP *)src == video_bitmap)
410   {
411     src_x += display->screens[display->default_screen].x;
412     src_y += display->screens[display->default_screen].y;
413   }
414
415   if ((BITMAP *)dest == video_bitmap)
416   {
417     dest_x += display->screens[display->default_screen].x;
418     dest_y += display->screens[display->default_screen].y;
419     freeze_mouse_flag = TRUE;
420     mouse_off = hide_mouse(display, dest_x, dest_y, width, height);
421   }
422
423   if (wait_for_vsync)
424   {
425     wait_for_vsync = FALSE;
426     vsync();
427   }
428
429   if (((XGCValues *)gc)->value_mask & GCClipMask)
430     masked_blit((BITMAP *)src, (BITMAP *)dest, src_x, src_y, dest_x, dest_y,
431                 width, height);
432   else
433     blit((BITMAP *)src, (BITMAP *)dest, src_x, src_y, dest_x, dest_y,
434          width, height);
435
436   if (mouse_off)
437     unhide_mouse(display);
438
439   freeze_mouse_flag = FALSE;
440 }
441
442 static BITMAP *Image_to_AllegroBitmap(Image *image)
443 {
444   BITMAP *bitmap;
445   byte *src_ptr = image->data;
446   byte pixel_mapping[MAX_COLORS];
447   unsigned int depth = 8;
448   int i, j, x, y;
449
450   /* allocate new allegro bitmap structure */
451   if ((bitmap = create_bitmap_ex(depth, image->width, image->height)) == NULL)
452     return NULL;
453
454   clear(bitmap);
455
456   /* try to use existing colors from the global colormap */
457   for (i=0; i<MAX_COLORS; i++)
458   {
459     int r, g, b;
460
461     if (!image->rgb.color_used[i])
462       continue;
463
464     r = image->rgb.red[i] >> 10;
465     g = image->rgb.green[i] >> 10;
466     b = image->rgb.blue[i] >> 10;
467
468     for (j=0; j<global_colormap_entries_used; j++)
469     {
470       if (r == global_colormap[j].r &&
471           g == global_colormap[j].g &&
472           b == global_colormap[j].b)            /* color found */
473       {
474         pixel_mapping[i] = j;
475         break;
476       }
477     }
478
479     if (j == global_colormap_entries_used)      /* color not found */
480     {
481       if (global_colormap_entries_used < MAX_COLORS)
482         global_colormap_entries_used++;
483
484       global_colormap[j].r = r;
485       global_colormap[j].g = g;
486       global_colormap[j].b = b;
487
488       pixel_mapping[i] = j;
489     }
490   }
491
492   /* copy bitmap data */
493   for (y=0; y<image->height; y++)
494     for (x=0; x<image->width; x++)
495       putpixel(bitmap, x, y, pixel_mapping[*src_ptr++]);
496
497   return bitmap;
498 }
499
500 static BITMAP *Read_PCX_to_AllegroBitmap(char *filename)
501 {
502   BITMAP *bitmap;
503   Image *image;
504
505   /* read the graphic file in PCX format to internal image structure */
506   if ((image = Read_PCX_to_Image(filename)) == NULL)
507     return NULL;
508
509   /* convert internal image structure to allegro bitmap structure */
510   if ((bitmap = Image_to_AllegroBitmap(image)) == NULL)
511     return NULL;
512
513   set_pallete(global_colormap);
514
515   return bitmap;
516 }
517
518 int Read_PCX_to_Pixmap(Display *display, Window window, GC gc, char *filename,
519                        Pixmap *pixmap, Pixmap *pixmap_mask)
520 {
521   BITMAP *bitmap;
522
523   if ((bitmap = Read_PCX_to_AllegroBitmap(filename)) == NULL)
524     return PCX_FileInvalid;
525
526   *pixmap = (Pixmap)bitmap;
527   *pixmap_mask = (Pixmap)bitmap;
528
529   return PCX_Success;
530 }
531
532 int XpmReadFileToPixmap(Display *display, Drawable d, char *filename,
533                         Pixmap *pixmap_return, Pixmap *shapemask_return,
534                         XpmAttributes *attributes)
535 {
536   BITMAP *bitmap;
537
538   if ((bitmap = Read_PCX_to_AllegroBitmap(filename)) == NULL)
539     return XpmOpenFailed;
540
541   *pixmap_return = (Pixmap)bitmap;
542
543   return XpmSuccess;
544 }
545
546 int XReadBitmapFile(Display *display, Drawable d, char *filename,
547                     unsigned int *width_return, unsigned int *height_return,
548                     Pixmap *bitmap_return,
549                     int *x_hot_return, int *y_hot_return)
550 {
551   BITMAP *bitmap;
552
553   if ((bitmap = Read_PCX_to_AllegroBitmap(filename)) == NULL)
554     return BitmapOpenFailed;
555
556   *width_return = bitmap->w;
557   *height_return = bitmap->h;
558   *x_hot_return = -1;
559   *y_hot_return = -1;
560   *bitmap_return = (Pixmap)bitmap;
561
562   return BitmapSuccess;
563 }
564
565 void XFreePixmap(Display *display, Pixmap pixmap)
566 {
567   if (pixmap != DUMMY_MASK &&
568       (is_memory_bitmap((BITMAP *)pixmap) ||
569        is_screen_bitmap((BITMAP *)pixmap)))
570     destroy_bitmap((BITMAP *)pixmap);
571 }
572
573 void XFreeGC(Display *display, GC gc)
574 {
575   XGCValues *gcv;
576
577   gcv = (XGCValues *)gc;
578   if (gcv)
579     free(gcv);
580 }
581
582 void XCloseDisplay(Display *display)
583 {
584   BITMAP *bitmap = video_bitmap;
585
586   if (is_screen_bitmap(bitmap))
587     destroy_bitmap(bitmap);
588   if (display->screens)
589     free(display->screens);
590   if (display)
591     free(display);
592 }
593
594 void XNextEvent(Display *display, XEvent *event_return)
595 {
596   while (!pending_events)
597     XPending(display);
598
599   memcpy(event_return, &event_buffer[pending_events], sizeof(XEvent));
600   pending_events--;
601 }
602
603 int XPending(Display *display)
604 {
605   int i, state;
606   static boolean joy_button_2 = FALSE;
607
608   /*!!!*/
609   int joystick_nr = 0;  /* CHANGE THIS! */
610   /*!!!*/
611
612   XKeyEvent *xkey;
613   XButtonEvent *xbutton;
614   XMotionEvent *xmotion;
615
616   /* joystick event (simulating keyboard event) */
617
618   state = get_joystick_state();
619
620   if (joy[joystick_nr].button[1].b && !joy_button_2)
621   {
622     pending_events++;
623     xkey = (XKeyEvent *)&event_buffer[pending_events];
624     xkey->type = KeyPress;
625     xkey->state = XK_B;
626     joy_button_2 = TRUE;
627   }
628   else if (!joy[joystick_nr].button[1].b && joy_button_2)
629   {
630     pending_events++;
631     xkey = (XKeyEvent *)&event_buffer[pending_events];
632     xkey->type = KeyRelease;
633     xkey->state = XK_B;
634     joy_button_2 = FALSE;
635   }
636
637   if (state && !joystick_event)
638   {
639     pending_events++;
640     xkey = (XKeyEvent *)&event_buffer[pending_events];
641     xkey->type = KeyPress;
642     xkey->state = state;
643     joystick_event = TRUE;
644     last_joystick_state = state;
645   }
646   else if ((state != last_joystick_state) && joystick_event)
647   {
648     pending_events++;
649     xkey = (XKeyEvent *)&event_buffer[pending_events];
650     xkey->type = KeyRelease;
651     xkey->state = last_joystick_state;
652     joystick_event = FALSE;
653   }
654
655   /* keyboard event */
656
657   for(i=0; i<OSD_MAX_KEY+1 && pending_events<MAX_EVENT_BUFFER; i++)
658   {
659     state = osd_key_pressed(i);
660
661     if (state != key_buffer[i])
662     {
663       key_buffer[i] = state;
664       pending_events++;
665       xkey = (XKeyEvent *)&event_buffer[pending_events];
666       xkey->type = (state & KeyPressMask ? KeyPress : KeyRelease);
667       xkey->state = i;
668     }
669   }
670
671   /* mouse motion event */
672
673   if (mouse_pos != last_mouse_pos && mouse_b != last_mouse_b)
674   {
675     last_mouse_pos = mouse_pos;
676     pending_events++;
677     xmotion = (XMotionEvent *)&event_buffer[pending_events];
678     xmotion->type = MotionNotify;
679     xmotion->x = mouse_x - display->screens[display->default_screen].x;
680     xmotion->y = mouse_y - display->screens[display->default_screen].y;
681
682
683     /*
684     return;
685     */
686
687   }
688
689   /* mouse button event */
690
691   if (mouse_b != last_mouse_b)
692   {
693     for(i=1; i<4; i<<=1)
694     {
695       if ((last_mouse_b & i) != (mouse_b & i))
696       {
697         pending_events++;
698         xbutton = (XButtonEvent *)&event_buffer[pending_events];
699         xbutton->type = (mouse_b & i ? ButtonPress : ButtonRelease);
700         xbutton->button = i;
701         xbutton->x = mouse_x - display->screens[display->default_screen].x;
702         xbutton->y = mouse_y - display->screens[display->default_screen].y;
703       }
704     }
705     last_mouse_b = mouse_b;
706   }
707
708   return pending_events;
709 }
710
711 KeySym XLookupKeysym(XKeyEvent *key_event, int index)
712 {
713   return key_event->state;
714 }
715
716 void sound_handler(struct SoundControl snd_ctrl)
717 {
718   int i;
719
720   if (snd_ctrl.fade_sound)
721   {
722     if (!playing_sounds)
723       return;
724
725     for(i=0; i<MAX_SOUNDS_PLAYING; i++)
726       if ((snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr) &&
727           !playlist[i].fade_sound)
728       {
729         playlist[i].fade_sound = TRUE;
730         if (voice_check(playlist[i].voice))
731           voice_ramp_volume(playlist[i].voice, 1000, 0);
732         playlist[i].loop = PSND_NO_LOOP;
733       }
734   }
735   else if (snd_ctrl.stop_all_sounds)
736   {
737     if (!playing_sounds)
738       return;
739     SoundServer_StopAllSounds();
740   }
741   else if (snd_ctrl.stop_sound)
742   {
743     if (!playing_sounds)
744       return;
745     SoundServer_StopSound(snd_ctrl.nr);
746   }
747
748   for(i=0; i<MAX_SOUNDS_PLAYING; i++)
749   {
750     if (!playlist[i].active || playlist[i].loop)
751       continue;
752
753     playlist[i].playingpos = voice_get_position(playlist[i].voice);
754     playlist[i].volume = voice_get_volume(playlist[i].voice);
755     if (playlist[i].playingpos == -1 || !playlist[i].volume)
756     {
757       deallocate_voice(playlist[i].voice);
758       playlist[i] = emptySoundControl;
759       playing_sounds--;
760     }
761   }
762
763   if (snd_ctrl.active)
764     SoundServer_InsertNewSound(snd_ctrl);
765 }
766
767 void NetworkServer(int port, int serveronly)
768 {
769   printf("Sorry, networking not supported in DOS version.\n");
770 }
771
772 #endif /* MSDOS */