1 /*
2 Copyright (C) 1994-1995 Apogee Software, Ltd.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 */
20 
21 #include <string.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <fcntl.h>
25 
26 #ifdef DOS
27 #include <dos.h>
28 #include <io.h>
29 #endif
30 
31 #include "rt_def.h"
32 #include "rt_main.h"
33 #include "rt_net.h"
34 #include "rt_com.h"
35 #include "_rt_net.h"
36 #include "rt_actor.h"
37 #include "rt_playr.h"
38 #include "isr.h"
39 #include "z_zone.h"
40 #include "develop.h"
41 #include "rottnet.h"
42 #include "rt_msg.h"
43 #include "rt_sound.h"
44 #include "rt_menu.h"
45 #include "rt_util.h"
46 #include "rt_rand.h"
47 #include "rt_game.h"
48 #include "rt_draw.h"
49 #include "myprint.h"
50 #include "rt_debug.h"
51 #include "rt_view.h"
52 #include "rt_battl.h"
53 #include "rt_dmand.h"
54 //MED
55 #include "memcheck.h"
56 
57 #if (SYNCCHECK == 1)
58 int            lastsynccheck;
59 COM_CheckSyncType PlayerSync[MAXPLAYERS];
60 #endif
61 
62 
63 CommandType * LocalCmds;
64 CommandType * ServerCmds;
65 
66 
67 int        controlupdatestartedtime=-1;
68 int        controlupdatetime=-1;
69 int        serverupdatetime=-1;
70 int        controlupdatestarted=0;
71 boolean    GamePaused=false;
72 
73 boolean    modemgame;
74 boolean    networkgame;
75 int        numplayers;
76 int        server;
77 boolean    IsServer;
78 boolean    standalone;
79 boolean    restartgame=false;
80 boolean    respawnactive=false;
81 boolean    playerdead=false;
82 boolean    controlschanged=true;
83 boolean    battlegibs=false;
84 boolean    remoteridicule = false;
85 /*
86 =============================================================================
87 
88 					LOCAL FUNCTION PROTOTYPES and VARIABLES
89 
90 =============================================================================
91 */
92 boolean  demorecord,
93 			demoplayback;
94 byte     *demoptr,
95 			*lastdemoptr,
96          *demobuffer=NULL;
97 boolean  demodone = false;
98 int oldmomx;
99 int oldmomy;
100 int oldspdang;
101 
102 static boolean GameCommandsStarted=false;
103 
104 static int oldcontrolbuf[3];
105 static int oldbuttonbits;
106 static CommandType * PlayerCmds[MAXPLAYERS];
107 static CommandType * ClientCmds[MAXPLAYERS];
108 
109 static boolean GotPlayersDesc[MAXPLAYERS];
110 static boolean PlayersReady[MAXPLAYERS];
111 static int     LastCommandTime[MAXPLAYERS];
112 
113 static CommandStatusType * CommandState[MAXPLAYERS+1];
114 
115 static boolean InProcessServer=false;
116 static int lastcontrolupdatetime;
117 static int largesttime;
118 static int PlayerStatus[MAXPLAYERS];
119 //static int syncservertime;
120 //static boolean FixingPackets;
121 static int controldivisor=1;
122 static int nextupdatetime;
123 static boolean UpdateServer=true;
124 
125 void CheckForPacket ( void );
126 void PrepareLocalPacket ( void );
127 void SendSyncCheckPacket ( void );
128 void AddModemSubPacket(void * incoming);
129 void SetPlayerDescription( void * pkt );
130 void UpdateDemoPlayback (int time);
131 int GetTypeSize (int type);
132 int MaxSpeedForCharacter(playertype *pstate);
133 
134 /*
135 =============================================================================
136 
137 						  Game Command Section
138 
139 =============================================================================
140 */
141 
142 //****************************************************************************
143 //
144 // ComError ()
145 //
146 //****************************************************************************
147 
148 #define ComError SoftError
149 #if 0
150 void ComError (char *error, ...)
151 {
152 #if 0
153 	va_list	argptr;
154 #endif
155 
156    SoftError(error);
157 #if 0
158    if (standalone==true)
159       {
160 	   va_start (argptr, error);
161       vprintf (error, argptr);
162 	   va_end (argptr);
163       }
164 #endif
165 }
166 #endif
167 
168 //****************************************************************************
169 //
170 // ConsoleIsServer()
171 //
172 //****************************************************************************
ConsoleIsServer(void)173 boolean ConsoleIsServer ( void )
174 {
175    if (modemgame==true)
176       {
177       if (networkgame==true)
178          {
179          if (rottcom->client==0)
180             {
181             return true;
182             }
183          }
184       }
185    return false;
186 }
187 
188 //****************************************************************************
189 //
190 // GamePacketSize()
191 //
192 //****************************************************************************
GamePacketSize(void)193 int GamePacketSize( void )
194 {
195    if ((remoteridicule == true) || (ConsoleIsServer() == true))
196       {
197       return GetTypeSize(COM_SOUNDANDDELTA);
198       }
199    else
200       return GetTypeSize(COM_TEXT);
201 }
202 
203 //****************************************************************************
204 //
205 // InitializeGameCommands()
206 //
207 //****************************************************************************
InitializeGameCommands(void)208 void InitializeGameCommands( void )
209 {
210    int i;
211    int j;
212 
213 	// default to player 0
214 
215    if (GameCommandsStarted==true)
216       return;
217 
218    GameCommandsStarted=true;
219 
220    if ((modemgame==true))
221       controldivisor=rottcom->ticstep;
222 
223    standalone=false;
224    IsServer=false;
225 
226    if (modemgame==true)
227       {
228 		consoleplayer=rottcom->consoleplayer;
229 
230       if (networkgame==true)
231          {
232          if (rottcom->client==0)
233             {
234             IsServer=true;
235             // turn it on absolutely for the server
236             remoteridicule = true;
237 				if (consoleplayer==0)
238                standalone=true;
239             }
240 			if (consoleplayer>0)
241 				consoleplayer--; // playernumber fixup
242          }
243       }
244 
245    if (standalone==false)
246       {
247       int size;
248 
249       size = GamePacketSize ();
250 
251 		for (i=0;i<numplayers;i++)
252          {
253          PlayerCmds[i]=(CommandType *)SafeLevelMalloc(sizeof(CommandType));
254          for (j=0;j<MAXCMDS;j++)
255             {
256             PlayerCommand(i,j)=SafeLevelMalloc(size);
257             }
258          }
259       }
260 
261 
262    // allocate local commands
263 
264    LocalCmds=(CommandType *)SafeLevelMalloc(sizeof(CommandType));
265    for (j=0;j<MAXCMDS;j++)
266       {
267       int size;
268 
269       size = GamePacketSize();
270 
271       LocalCommand(j)=SafeLevelMalloc(size);
272       memset(LocalCommand(j),COM_DELTANULL,size);
273       }
274 
275    CommandState[0]=(CommandStatusType *)SafeLevelMalloc(sizeof(CommandStatusType));
276 
277    if (modemgame==true)
278       {
279       for (i=0;i<numplayers;i++)
280          {
281          PlayerStatus[i]=player_ingame;
282          }
283       if (networkgame==true)
284          {
285          server=1;
286 
287          // initialize the Server
288 
289          if (IsServer==true)
290             {
291             server=0;
292             ServerCmds=(CommandType *)SafeMalloc(sizeof(CommandType));
293             for (j=0;j<MAXCMDS;j++)
294                {
295                int size;
296                size=( (numplayers * GetTypeSize(COM_TEXT)) +
297                       GetTypeSize(COM_SOUNDANDDELTA) +
298                       sizeof(COM_ServerHeaderType) -
299                       sizeof(byte)
300                     );
301                ServerCommand(j)=SafeMalloc( size );
302                memset(ServerCommand(j),COM_DELTANULL,size);
303                }
304             for (i=1;i<=numplayers;i++)
305                {
306                CommandState[i]=(CommandStatusType *)
307                                SafeMalloc(sizeof(CommandStatusType));
308                }
309 				for (i=0;i<numplayers;i++)
310                {
311                ClientCmds[i]=(CommandType *)SafeMalloc(sizeof(CommandType));
312                for (j=0;j<MAXCMDS;j++)
313                   {
314                   int size;
315 
316                   size=GetTypeSize(COM_SOUNDANDDELTA);
317                   ClientCommand(i,j)=SafeMalloc(size);
318                   memset(ClientCommand(i,j),COM_DELTANULL,size);
319                   }
320                }
321             }
322          }
323 		else // must be a two player game
324          {
325 			server=consoleplayer^1;
326          }
327       }
328 #if 0
329 #if (DEVELOPMENT == 1)
330       if (IsServer)
331          ComError("I am the server\n");
332       ComError("consoleplayer=%ld\n",consoleplayer);
333       ComError("server=%ld mynumber=%ld\n",server,consoleplayer);
334 #endif
335 #endif
336 }
337 
338 
339 //****************************************************************************
340 //
341 // ShutdownGameCommands()
342 //
343 //****************************************************************************
ShutdownGameCommands(void)344 void ShutdownGameCommands( void )
345 {
346    int i;
347    int j;
348 
349    if (GameCommandsStarted==false)
350       return;
351 
352    GameCommandsStarted=false;
353 
354 	// free up playercmds;
355    if (standalone==false)
356       {
357 	   for (i=0;i<numplayers;i++)
358          {
359          for (j=0;j<MAXCMDS;j++)
360             {
361             if (PlayerCommand(i,j))
362                {
363                SafeFree(PlayerCommand(i,j));
364                PlayerCommand(i,j)=NULL;
365                }
366             }
367          SafeFree( PlayerCmds[i] );
368          PlayerCmds[i]=NULL;
369          }
370       }
371 
372    // free up command status
373 
374    SafeFree(CommandState[0]);
375    CommandState[0]=NULL;
376 
377    if (modemgame==true)
378       {
379 
380       // free up local commands
381 
382       for (j=0;j<MAXCMDS;j++)
383          {
384          if (LocalCommand(j))
385             {
386             SafeFree(LocalCommand(j));
387             LocalCommand(j)=NULL;
388             }
389          }
390       SafeFree(LocalCmds);
391       LocalCmds=NULL;
392 
393 
394       // free up Server
395 
396       if (networkgame==true)
397          {
398          if (IsServer==true)
399             {
400             for (j=0;j<MAXCMDS;j++)
401                {
402                if (ServerCommand(j))
403                   {
404                   SafeFree(ServerCommand(j));
405                   ServerCommand(j)=NULL;
406                   }
407                }
408             SafeFree(ServerCmds);
409             ServerCmds=NULL;
410             for (i=1;i<=numplayers;i++)
411                {
412                SafeFree(CommandState[i]);
413                CommandState[i]=NULL;
414                }
415 				for (i=0;i<numplayers;i++)
416                {
417                for (j=0;j<MAXCMDS;j++)
418                   {
419                   if (ClientCommand(i,j))
420                      {
421                      SafeFree(ClientCommand(i,j));
422                      ClientCommand(i,j)=NULL;
423                      }
424                   }
425                SafeFree( ClientCmds[i] );
426                ClientCmds[i]=NULL;
427                }
428             }
429          }
430       }
431 }
432 
433 
434 
435 
436 /*
437 =============================================================================
438 
439 						  Client Controls Section
440 
441 =============================================================================
442 */
443 
444 
445 //****************************************************************************
446 //
447 // ShutdownClientControls ()
448 //
449 //****************************************************************************
450 
ShutdownClientControls(void)451 void ShutdownClientControls ( void )
452 {
453    int i;
454 #if (DEVELOPMENT == 1)
455    SoftError ("LARGEST time difference=%ld\n",largesttime);
456 #endif
457    controlupdatestarted=0;
458    for (i=0;i<numplayers;i++)
459        {
460        if (PlayerStatus[i] == player_leftgame)
461           PlayerStatus[i]=player_ingame;
462        }
463 }
464 
465 
466 //****************************************************************************
467 //
468 // StartupClientControls ()
469 //
470 //****************************************************************************
471 
StartupClientControls(void)472 void StartupClientControls ( void )
473 {
474    int i,j;
475 
476    if (controlupdatestarted==1)
477       return;
478 
479    controlupdatestarted=1;
480 
481    memset(oldcontrolbuf,-1,sizeof(oldcontrolbuf));
482    oldbuttonbits=-1;
483    controlschanged=true;
484 
485    INL_GetMouseDelta(&i,&i);
486 
487 
488    locplayerstate->dmomx = 0;
489    locplayerstate->dmomy = 0;
490    locplayerstate->angle = 0;
491    locplayerstate->topspeed=MaxSpeedForCharacter(locplayerstate);
492 
493 
494    CalcTics();
495    CalcTics();
496 
497 //   FixingPackets=false;
498 
499 	memset (controlbuf, 0, sizeof (controlbuf));
500    buttonbits = 0;
501    lastpolltime=-1;
502    IN_ClearKeyboardQueue ();
503 
504    if (modemgame==true)
505       {
506       controlupdatetime=controlsynctime+(VBLCOUNTER*2);
507       SoftError("Controls started at %ld\n",controlupdatetime);
508       }
509    else if (demoplayback || demorecord)
510       {
511       ISR_SetTime(20);
512       oldtime = 20;
513       controlupdatetime=20;
514       }
515    else
516       controlupdatetime=GetTicCount();
517 
518    controlupdatetime-=(controlupdatetime%controldivisor);
519 
520    serverupdatetime=controlupdatetime;
521    oldpolltime=controlupdatetime;
522    nextupdatetime=oldpolltime;
523 #if (SYNCCHECK == 1)
524    lastsynccheck=oldpolltime+CHECKSYNCTIME;
525 #endif
526    controlupdatestartedtime=controlupdatetime;
527 
528    for( j = 0; j < numplayers; j++ )
529       {
530       memset( PLAYERSTATE[ j ].buttonheld, 0,
531          sizeof( PLAYERSTATE[ j ].buttonheld ) );
532       memset( PLAYERSTATE[ j ].buttonstate, 0,
533          sizeof( PLAYERSTATE[ j ].buttonstate ) );
534       }
535 
536    for (i=0;i<MAXCMDS;i++)
537       {
538       ServerCommandNumberStatus( i ) = cs_notarrived;
539       }
540 
541    LastCommandTime[0]=controlupdatetime-controldivisor;
542    if (IsServer==true)
543       {
544       int size;
545 
546       UpdateServer=true;
547       size=( (numplayers * GetTypeSize(COM_TEXT)) +
548                GetTypeSize(COM_SOUNDANDDELTA) +
549                sizeof(COM_ServerHeaderType) -
550                sizeof(byte)
551             );
552 
553       for (j=0;j<numplayers;j++)
554          {
555 	      for (i=0;i<MAXCMDS;i++)
556             {
557             ClientCommandNumberStatus( j , i ) = cs_notarrived;
558             }
559          LastCommandTime[j]=controlupdatetime-controldivisor;
560          }
561       for (i=0;i<MAXCMDS;i++)
562          memset(ServerCommand(i),COM_DELTANULL,size);
563       }
564    else if (modemgame==true)
565       {
566       int nump;
567 
568       nump=numplayers;
569       if (nump<2) nump=2;
570 
571       for (i=0;i<nump;i++)
572          {
573          LastCommandTime[i]=controlupdatetime-controldivisor;
574          }
575       }
576 
577 
578 #if (DEVELOPMENT == 1)
579 //   ComError("StartupClientControls: GetTicCount()=%ld oldtime=%ld controlupdatetime=%ld\n",GetTicCount(),oldtime,controlupdatetime);
580 #endif
581 
582    if ((demoplayback==false) && (standalone==false))
583       {
584       if (modemgame==true)
585          {
586          while (GetTicCount()<(controlupdatetime-10))
587             {
588             CalcTics();
589             }
590          }
591       lastcontrolupdatetime=GetTicCount();
592       largesttime=0;
593       PollControls();
594       }
595    if (standalone==true)
596       printf("Packet Server started\n");
597 }
598 
599 
600 
601 //****************************************************************************
602 //
603 // UpdateClientControls ()
604 //
605 //****************************************************************************
606 
607 static boolean InUCC=false;
UpdateClientControls(void)608 void UpdateClientControls ( void )
609 {
610    int time;
611 //   int delta;
612 
613    if (controlupdatestarted==0)
614       return;
615 
616    if (InUCC)
617       return;
618    else
619       InUCC = true;
620 
621    wami(6);
622 
623 #if 0
624 
625    delta=GetTicCount()-lastcontrolupdatetime;
626    if (delta>largesttime)
627       {
628       if (delta>10)
629          largesttime=delta;
630       largesttime=delta;
631       }
632 
633 #endif
634    lastcontrolupdatetime=GetTicCount();
635 
636    if (standalone==false)
637       {
638       time=GetTicCount();
639 
640       // if we are a fixing the current packet stop update of deltas
641       // in non-network games.
642       if (
643            (networkgame == false) &&
644            (ServerCommandStatus(oldpolltime)==cs_fixing)
645          )
646          {
647          time=controlupdatetime-controldivisor;
648          }
649 
650       while (time>=controlupdatetime)
651          {
652          MoveType * Delta;
653          boolean soundready;
654 
655          soundready = SD_SoundDataReady();
656 
657          if (demoplayback==true)
658             {
659             UpdateDemoPlayback(controlupdatetime);
660             }
661 //         else
662 //            {
663 //            PollControls();
664 //            }
665 
666          if (
667              (memcmp(&controlbuf[0],&oldcontrolbuf[0],sizeof(controlbuf))!=0) ||
668              (buttonbits!=oldbuttonbits)
669             )
670             {
671             controlschanged=true;
672             memcpy(&oldcontrolbuf[0],&controlbuf[0],sizeof(controlbuf));
673             oldbuttonbits=buttonbits;
674             }
675          else
676             {
677             controlschanged=false;
678             }
679 
680          if ((controlschanged==false) && (soundready==false))
681             {
682             NullMoveType * NullDelta;
683 
684             NullDelta=(NullMoveType *)NextLocalCommand();
685             NullDelta->type=COM_DELTANULL;
686             }
687          else
688             {
689             Delta=(MoveType *)NextLocalCommand();
690             Delta->type=COM_DELTA;
691             Delta->momx=(controlbuf[0]>>1);
692             Delta->momy=(controlbuf[1]>>1);
693             Delta->dangle=controlbuf[2]>>11;
694             Delta->buttons=buttonbits;
695 
696             // See if we need to update sound packet
697 
698             if (soundready==true)
699                {
700                COM_SoundType * sndpkt;
701                recordstate status;
702 
703                if (remoteridicule == false)
704                   Error("Attempt to record Remote Ridicule without adequate storage");
705                sndpkt=(COM_SoundType *)Delta->Sounddata;
706 
707                // Turn the packet into a COM_SOUNDANDDELTA packet
708 
709                Delta->type=COM_SOUNDANDDELTA;
710                status = SD_GetSoundData ( &(sndpkt->data[0]),
711                                           COM_SOUND_BUFFERSIZE );
712                switch (status)
713                   {
714                   case rs_nodata:
715                      Delta->type=COM_DELTA;
716                      break;
717                   case rs_newsound:
718                      sndpkt->type=COM_SOUND_START_TRANSMISSION;
719                      break;
720                   case rs_endsound:
721                      sndpkt->type=COM_SOUND_END_TRANSMISSION;
722                      break;
723                   case rs_data:
724                      sndpkt->type=COM_SOUND_NORMAL_TRANSMISSION;
725                      break;
726                   default:
727                      Error("Illegal return value for SD_GetSoundData");
728                      break;
729                   }
730                }
731             if (demorecord==true)
732                RecordDemoCmd();
733             }
734          PrepareLocalPacket();
735 
736          if (
737               (controlupdatetime != -1) &&
738               (controlupdatetime > (lastpolltime+MAXPOLLTICS)) &&
739               (demoplayback==false)
740             )
741             {
742             controlbuf[0] = controlbuf[1] = controlbuf[2] = 0;
743             }
744          }
745       }
746    if (modemgame==true)
747       {
748       CheckForPacket ();
749       }
750 
751    if ((standalone == false) && (IsServer==true) && (UpdateServer==true))
752       ProcessServer();
753 
754 // take out
755    if (modemgame==true)
756       {
757 //#if (DEVELOPMENT == 1)
758       if (PanicPressed==true)
759          {
760          Error("Game Aborted. Scroll Lock pressed\n");
761          }
762 //#endif
763 		if (Keyboard[sc_Insert] && Keyboard[sc_Q])
764          Error("Game Aborted. Insert->Q pressed\n");
765       }
766 
767    InUCC = false;
768 
769    waminot();
770 }
771 
772 //****************************************************************************
773 //
774 // PlayerInGame()
775 //
776 //****************************************************************************
PlayerInGame(int p)777 boolean PlayerInGame ( int p )
778 {
779    if (PlayerStatus[p]!=player_ingame)
780       return false;
781    return true;
782 }
783 
784 /*
785 =============================================================================
786 
787 						  Packet Section
788 
789 =============================================================================
790 */
791 
792 //****************************************************************************
793 //
794 // CheckForPacket()
795 //
796 //****************************************************************************
CheckForPacket(void)797 void CheckForPacket ( void )
798 {
799    wami(7);
800    while (ReadPacket()==true)
801       {
802       if (badpacket==0)
803          {
804          ProcessPacket(&ROTTpacket[0], rottcom->remotenode);
805          #if (DEVELOPMENT == 1)
806 //         ComError("CheckForPacket: from=%ld\n",rottcom->remotenode);
807          #endif
808          }
809       else
810          RequestPacket (LastCommandTime[rottcom->remotenode]+controldivisor, rottcom->remotenode, controldivisor);
811       }
812    waminot();
813 }
814 
815 
816 //****************************************************************************
817 //
818 // AddRemoteRidiculeCommand()
819 //
820 //****************************************************************************
AddRemoteRidiculeCommand(int player,int towho,int num)821 void AddRemoteRidiculeCommand ( int player, int towho, int num )
822 {
823    ((COM_RemoteRidiculeType *)NextLocalCommand())->type=COM_REMRID;
824    ((COM_RemoteRidiculeType *)NextLocalCommand())->num=num;
825    ((COM_RemoteRidiculeType *)NextLocalCommand())->player=player;
826    ((COM_RemoteRidiculeType *)NextLocalCommand())->towho=towho;
827 
828    PrepareLocalPacket();
829 }
830 
831 //****************************************************************************
832 //
833 // ProcessRemoteRidicule()
834 //
835 //****************************************************************************
ProcessRemoteRidicule(void * pkt)836 void ProcessRemoteRidicule ( void * pkt )
837    {
838    COM_RemoteRidiculeType * remrot;
839    char name[ 50 ];
840    int from;
841    int who;
842 
843    remrot = (COM_RemoteRidiculeType *)pkt;
844    from   = remrot->player;
845    who    = remrot->towho;
846    if ( ( who == consoleplayer ) || ( who == MSG_DIRECTED_TO_ALL ) ||
847       ( ( who == MSG_DIRECTED_TO_TEAM ) && ( BATTLE_Team[ from ] ==
848       BATTLE_Team[ consoleplayer ] ) ) )
849       {
850       strcpy( name, "(� RR from " );
851       strcat( name, PLAYERSTATE[from].codename );
852       strcat( name, ")" );
853       AddMessage( name, MSG_REMOTERIDICULE );
854 
855       SD_Play( SD_REMOTEM1SND + remrot->num );
856       }
857    }
858 
859 //****************************************************************************
860 //
861 // AddEndGameCommand()
862 //
863 //****************************************************************************
AddEndGameCommand(void)864 void AddEndGameCommand ( void )
865 {
866    ((COM_EndGameType *)NextLocalCommand())->type=COM_ENDGAME;
867 
868    PrepareLocalPacket();
869 }
870 
871 //****************************************************************************
872 //
873 // AddGameEndCommand()
874 //
875 //****************************************************************************
AddGameEndCommand(void)876 void AddGameEndCommand ( void )
877 {
878    ((COM_GameEndType *)NextLocalCommand())->type=COM_GAMEEND;
879 
880    PrepareLocalPacket();
881 }
882 
883 //****************************************************************************
884 //
885 // AddQuitCommand()
886 //
887 //****************************************************************************
AddQuitCommand(void)888 void AddQuitCommand ( void )
889 {
890    ((COM_QuitType *)NextLocalCommand())->type=COM_QUIT;
891    PrepareLocalPacket();
892 }
893 
894 //****************************************************************************
895 //
896 // AddExitCommand()
897 //
898 //****************************************************************************
AddExitCommand(void)899 void AddExitCommand ( void )
900 {
901    ((COM_ExitType *)NextLocalCommand())->type=COM_EXIT;
902    PrepareLocalPacket();
903 }
904 
905 //****************************************************************************
906 //
907 // AddPauseStateCommand()
908 //
909 //****************************************************************************
AddPauseStateCommand(int type)910 void AddPauseStateCommand ( int type )
911 {
912    ((COM_PauseType *)NextLocalCommand())->type=type;
913 
914    PrepareLocalPacket();
915 }
916 
917 
918 //****************************************************************************
919 //
920 // AddRespawnCommand()
921 //
922 //****************************************************************************
AddRespawnCommand(void)923 void AddRespawnCommand ( void )
924 {
925    if (respawnactive==true)
926       return;
927 
928    respawnactive=true;
929 
930    ((COM_RespawnType *)NextLocalCommand())->type=COM_RESPAWN;
931 
932    PrepareLocalPacket();
933 }
934 
935 
936 //****************************************************************************
937 //
938 // AddTextMessage()
939 //
940 //****************************************************************************
AddTextMessage(char * message,int length,int towho)941 void AddTextMessage
942    (
943    char *message,
944    int   length,
945    int   towho
946    )
947 
948    {
949    COM_TextType *Text;
950 
951    Text = ( COM_TextType * )NextLocalCommand();
952 
953    Text->type = COM_TEXT;
954    memset( &Text->string[ 0 ], 0, COM_MAXTEXTSTRINGLENGTH );
955 
956    if ( length >= COM_MAXTEXTSTRINGLENGTH )
957       {
958       length = COM_MAXTEXTSTRINGLENGTH - 1;
959       }
960 
961    memcpy( &Text->string[ 0 ], message, length );
962 
963    Text->towho = towho;
964 
965    PrepareLocalPacket();
966    }
967 
968 
969 //****************************************************************************
970 //
971 // PrepareLocalPacket
972 //
973 //****************************************************************************
974 
PrepareLocalPacket(void)975 void PrepareLocalPacket ( void )
976 {
977    MoveType * pkt;
978 
979    wami(8);
980 
981    pkt=(MoveType *)NextLocalCommand();
982 
983    pkt->time=controlupdatetime;
984 
985    if (networkgame==false) // Whether it is a modem game or not we do this
986       {
987 		AddClientPacket (pkt, consoleplayer);
988       if (modemgame==false)
989          {
990          ServerCommandStatus ( controlupdatetime ) = cs_ready;
991          }
992       }
993 
994    if (modemgame==true)
995       SendPacket (pkt, server);
996 
997 #if (DEVELOPMENT == 1)
998 //   ComError("packet sent: realtime=%ld time=%ld type=%ld dest=%ld\n",GetTicCount(),pkt->time,pkt->type,server);
999 #endif
1000 
1001    controlupdatetime+=controldivisor;
1002    waminot();
1003 }
1004 
1005 
1006 
1007 //****************************************************************************
1008 //
1009 // GetPacketSize ()
1010 //
1011 //****************************************************************************
1012 
GetPacketSize(void * pkt)1013 int GetPacketSize (void * pkt)
1014 {
1015    int size;
1016 
1017    switch (((MoveType *)pkt)->type)
1018       {
1019       case COM_DELTA:
1020          size=sizeof(MoveType);
1021          break;
1022       case COM_DELTANULL:
1023          size=sizeof(NullMoveType);
1024          break;
1025       case COM_REQUEST:
1026          size=sizeof(COM_RequestType);
1027          break;
1028       case COM_FIXUP:
1029          size=sizeof(COM_FixupType);
1030          break;
1031       case COM_TEXT:
1032          size=sizeof(COM_TextType);
1033          break;
1034       case COM_PAUSE:
1035          size=sizeof(COM_PauseType);
1036          break;
1037       case COM_QUIT:
1038          size=sizeof(COM_QuitType);
1039          break;
1040       case COM_EXIT:
1041          size=sizeof(COM_ExitType);
1042          break;
1043       case COM_REMRID:
1044          size=sizeof(COM_RemoteRidiculeType);
1045          break;
1046       case COM_RESPAWN:
1047          size=sizeof(COM_RespawnType);
1048          break;
1049       case COM_UNPAUSE:
1050          size=sizeof(COM_UnPauseType);
1051          break;
1052       case COM_SERVER:
1053          size=sizeof(COM_ServerHeaderType);
1054          size-=sizeof(byte);
1055          break;
1056       case COM_GAMEDESC:
1057          size=sizeof(COM_GamePlayerType);
1058          break;
1059       case COM_GAMEEND:
1060          size=sizeof(COM_GameEndType);
1061          break;
1062       case COM_GAMEPLAY:
1063          size=DUMMYPACKETSIZE;
1064          break;
1065       case COM_GAMEACK:
1066          size=sizeof(COM_GameAckType);
1067          break;
1068       case COM_GAMEMASTER:
1069          size=sizeof(COM_GameMasterType);
1070          break;
1071       case COM_ENDGAME:
1072          size=sizeof(COM_EndGameType);
1073          break;
1074       case COM_SYNCTIME:
1075          size=sizeof(COM_SyncType);
1076          break;
1077 #if (SYNCCHECK == 1)
1078       case COM_SYNCCHECK:
1079          size=sizeof(COM_CheckSyncType);
1080          break;
1081 #endif
1082       case COM_SOUNDANDDELTA:
1083          size=sizeof(MoveType)+sizeof(COM_SoundType);
1084          break;
1085       default:
1086          Error("Unhandled packet type in GetPacketSize type=%ld",((MoveType *)pkt)->type);
1087          break;
1088       }
1089 
1090    return size;
1091 }
1092 
1093 //****************************************************************************
1094 //
1095 // GetTypeSize ()
1096 //
1097 //****************************************************************************
1098 
GetTypeSize(int type)1099 int GetTypeSize (int type)
1100 {
1101    byte pkt[2];
1102 
1103    pkt[0]=(byte)type;
1104    return ( GetPacketSize(&(pkt[0])) );
1105 }
1106 
1107 //****************************************************************************
1108 //
1109 // GetServerPacketSize ()
1110 //
1111 //****************************************************************************
1112 
GetServerPacketSize(void * pkt)1113 int GetServerPacketSize (void * pkt)
1114 {
1115    int i;
1116    byte * ptr;
1117    COM_ServerHeaderType * serverpkt;
1118 
1119    serverpkt=(COM_ServerHeaderType *)pkt;
1120    if (serverpkt->type==COM_SERVER)
1121       {
1122       ptr=&serverpkt->data;
1123 
1124       for (i=0;i<serverpkt->numpackets;i++)
1125          {
1126          ptr+=GetPacketSize(ptr);
1127          }
1128       return ((byte *)ptr-(byte *)pkt);
1129       }
1130    else
1131       return GetPacketSize(pkt);
1132 }
1133 
1134 //****************************************************************************
1135 //
1136 // SendPacket ()
1137 //
1138 //****************************************************************************
1139 
SendPacket(void * pkt,int dest)1140 void SendPacket (void * pkt, int dest)
1141 {
1142    if ((networkgame==false) && (PlayerStatus[dest]!=player_ingame))
1143       return;
1144    if ((IsServer==true) && (dest==server) && (standalone==false)) // must be client on top of server
1145       ProcessPacket(pkt,dest);
1146    else if ((IsServer==false) && (dest!=server) && (standalone==false)) // We shouldn't be sending as client to anyone else
1147       ComError("SendPacket:Problems\n");
1148    else
1149       WritePacket(pkt,GetPacketSize(pkt),dest);
1150 #if (DEVELOPMENT == 1)
1151 //   ComError( "SendPacket: time=%ld dest=%ld\n",((MoveType *)pkt)->time,dest);
1152 #endif
1153 }
1154 
1155 //****************************************************************************
1156 //
1157 // ResetCurrentCommand ()
1158 //
1159 //****************************************************************************
1160 
ResetCurrentCommand(void)1161 void ResetCurrentCommand ( void )
1162 {
1163    ServerCommandStatus(oldpolltime)=cs_notarrived;
1164 }
1165 
1166 //****************************************************************************
1167 //
1168 // BroadcastServerPacket ()
1169 //
1170 //****************************************************************************
1171 
BroadcastServerPacket(void * pkt,int size)1172 void BroadcastServerPacket (void * pkt, int size)
1173 {
1174    int i;
1175 
1176 
1177 	for (i=0;i<numplayers;i++)
1178       {
1179       if (PlayerStatus[i]!=player_ingame)
1180          continue;
1181 //      if ((standalone==false) && (i==consoleplayer))
1182 //         ProcessPacket(pkt,i);
1183 //      else
1184          WritePacket((byte *)pkt,size,i);
1185       }
1186 }
1187 
1188 
1189 //****************************************************************************
1190 //
1191 // ResendLocalPackets ()
1192 //
1193 //****************************************************************************
1194 
ResendLocalPackets(int time,int dest,int numpackets)1195 void ResendLocalPackets (int time, int dest, int numpackets)
1196 {
1197    int cmd;
1198    MoveType * pkt;
1199 
1200    cmd = CommandAddress(time);
1201 
1202 #if 0
1203    if (networkgame==false)
1204       {
1205       int nump;
1206       nump=controlupdatetime-time;
1207       if (nump>numpackets)
1208          numpackets=nump;
1209       }
1210 #endif
1211 
1212    if (controlupdatetime<=time)
1213       return;
1214 
1215    pkt = (MoveType *)LocalCommand(cmd);
1216 
1217    if (pkt->time!=time)
1218       {
1219       Error( "CLIENT: Could not find packet to resend\ntime=%ld packettime=%ld controlupdatetime=%ld\n",
1220              time, pkt->time, controlupdatetime);
1221       }
1222    else
1223       {
1224       byte * tempbuf;
1225       byte * tempptr;
1226       byte * tempstart;
1227       COM_FixupType * fixup;
1228       int i;
1229       int starti;
1230       int size;
1231       boolean done;
1232 
1233       // allocate some space
1234 
1235       tempbuf=SafeMalloc(MAXCOMBUFFERSIZE);
1236 
1237       fixup=(COM_FixupType *)tempbuf;
1238 
1239       fixup->type=COM_FIXUP;
1240       tempstart=&(fixup->data);
1241 
1242       done=false;
1243       i=0;
1244       while (done==false)
1245          {
1246          tempptr=tempstart;
1247          starti=i;
1248          fixup->time=( (MoveType *)LocalCommand(cmd) )->time;
1249          for (;i<numpackets;i++)
1250             {
1251             pkt = (MoveType *)LocalCommand(cmd);
1252             size=GetPacketSize(pkt);
1253 
1254             if (((tempptr+size)-tempbuf)>MAXCOMBUFFERSIZE)
1255                {
1256                break;
1257                }
1258             memcpy(tempptr,pkt,size);
1259             tempptr+=size;
1260             cmd = (cmd + controldivisor) & (MAXCMDS-1);
1261             }
1262          fixup->numpackets=i-starti;
1263          WritePacket(tempbuf,tempptr-tempbuf,dest);
1264          if (i==numpackets)
1265             done=true;
1266          }
1267 
1268       SafeFree(tempbuf);
1269       }
1270 }
1271 
1272 //****************************************************************************
1273 //
1274 // ResendServerPackets ()
1275 //
1276 //****************************************************************************
1277 
ResendServerPackets(int time,int dest,int numpackets)1278 void ResendServerPackets (int time, int dest, int numpackets)
1279 {
1280    int cmd;
1281    COM_ServerHeaderType * serverpkt;
1282 
1283 
1284    cmd = CommandAddress(time);
1285 
1286    if (serverupdatetime<=time)
1287       return;
1288 
1289    serverpkt = (COM_ServerHeaderType *)ServerCommand(cmd);
1290 
1291    if (serverpkt->time!=time)
1292       {
1293       Error( "SERVER: Could not find packet to resend\ntime=%ld packettime=%ld serverupdatetime=%ld\n",
1294              time, serverpkt->time,serverupdatetime);
1295       }
1296    else
1297       {
1298       byte * tempbuf;
1299       byte * tempptr;
1300       byte * tempstart;
1301       COM_FixupType * fixup;
1302       int i;
1303       int starti;
1304       int size;
1305       boolean done;
1306 
1307       // allocate some space
1308 
1309       tempbuf=SafeMalloc(MAXCOMBUFFERSIZE);
1310 
1311       fixup=(COM_FixupType *)tempbuf;
1312 
1313       fixup->type=COM_FIXUP;
1314       tempstart=&(fixup->data);
1315 
1316       done=false;
1317       i=0;
1318       while (done==false)
1319          {
1320          tempptr=tempstart;
1321          starti=i;
1322          fixup->time=( (MoveType *)ServerCommand(cmd) )->time;
1323          for (;i<numpackets;i++)
1324             {
1325             serverpkt = (COM_ServerHeaderType *)ServerCommand(cmd);
1326             size=GetServerPacketSize(serverpkt);
1327 
1328             if (((tempptr+size)-tempbuf)>MAXCOMBUFFERSIZE)
1329                {
1330                break;
1331                }
1332             memcpy(tempptr,serverpkt,size);
1333             tempptr+=size;
1334             cmd = (cmd + controldivisor) & (MAXCMDS-1);
1335             }
1336          fixup->numpackets=i-starti;
1337          WritePacket(tempbuf,tempptr-tempbuf,dest);
1338          if (i==numpackets)
1339             done=true;
1340          }
1341 
1342       SafeFree(tempbuf);
1343       }
1344 }
1345 
1346 
1347 //****************************************************************************
1348 //
1349 // ResendPacket (incoming packet, whoever requested it)
1350 //
1351 //****************************************************************************
1352 
ResendPacket(void * pkt,int dest)1353 void ResendPacket (void * pkt, int dest)
1354 {
1355    int time;
1356    COM_RequestType * request;
1357 
1358    if ((networkgame==false) && (PlayerStatus[dest]!=player_ingame))
1359       return;
1360 
1361    request=(COM_RequestType * )pkt;
1362    time=request->time;
1363 
1364    ComError( "RESEND request received at %ld\n packet time=%ld dest=%ld numpackets=%ld\n",
1365              GetTicCount(), time, dest, request->numpackets);
1366 
1367    if (IsServer==true)
1368       {
1369       if ((dest==server) && (standalone==false))
1370          Error("Trying to resend packets to client on top of server\n");
1371       ComError( "RESEND SERVER serverupdatetime=%ld\n",serverupdatetime);
1372       if (IsServerCommandReady ( time ) == true)
1373          ResendServerPackets(time,dest,request->numpackets);
1374       else
1375          ComError( "RESEND SERVER time=%ld is not ready\n",time);
1376       }
1377    else
1378       {
1379       ResendLocalPackets(time,dest,request->numpackets);
1380       }
1381 }
1382 
1383 //****************************************************************************
1384 //
1385 // FixupPacket ()
1386 //
1387 //****************************************************************************
1388 
FixupPacket(void * pkt,int src)1389 void FixupPacket (void * pkt, int src)
1390 {
1391    COM_FixupType * fix;
1392    int i;
1393    int time;
1394    byte * ptr;
1395 
1396    fix=(COM_FixupType *)pkt;
1397 
1398    ComError( "Fixup received at %ld, time=%ld numpackets=%ld\n", GetTicCount(), fix->time, fix->numpackets);
1399 #if 0
1400    if (networkgame==false)
1401       FixingPackets=false;
1402 #endif
1403    time=fix->time;
1404    ptr=&(fix->data);
1405 
1406    for (i=0;i<fix->numpackets;i++,time+=controldivisor)
1407       {
1408       if (time == (LastCommandTime[src]+controldivisor))
1409          LastCommandTime[src]=time;
1410 
1411       if (IsServer==true)
1412          {
1413          if (ClientCommandStatus(src, time)!=cs_fixing)
1414             {
1415             ComError("Server Received fixup with no bad packet time=%ld from %ld\n",time,src);
1416             }
1417          else
1418             {
1419             AddSubPacket(ptr, src);
1420             }
1421          ptr+=GetPacketSize(ptr);
1422          }
1423       else
1424          {
1425          if (ServerCommandStatus(time)!=cs_fixing)
1426             {
1427             ComError("Client Received fixup with no bad packet time=%ld from %ld\n",time,src);
1428             }
1429          else
1430             {
1431             if (networkgame==true)
1432                {
1433                AddServerSubPacket( (COM_ServerHeaderType *)ptr );
1434                }
1435             else
1436                {
1437                AddModemSubPacket(ptr);
1438                }
1439             }
1440          ptr+=GetServerPacketSize(ptr);
1441          }
1442       }
1443 }
1444 
1445 #if (SYNCCHECK == 1)
1446 //****************************************************************************
1447 //
1448 // CheckForSyncCheck
1449 //
1450 //****************************************************************************
1451 
CheckForSyncCheck(void)1452 void CheckForSyncCheck ( void )
1453 {
1454    int i;
1455 
1456 
1457    if (modemgame==true)
1458       {
1459       if (oldpolltime==lastsynccheck)
1460          {
1461          for (i=0;i<numplayers;i++)
1462             {
1463             PlayerSync[i].x=PLAYER[i]->x;
1464             PlayerSync[i].y=PLAYER[i]->y;
1465             PlayerSync[i].z=PLAYER[i]->z;
1466             PlayerSync[i].angle=PLAYER[i]->angle;
1467             }
1468          PlayerSync[0].randomindex=GetRNGindex();
1469          PlayerSync[0].synctime=lastsynccheck;
1470          SendSyncCheckPacket();
1471          lastsynccheck+=CHECKSYNCTIME;
1472          }
1473       if (oldpolltime>lastsynccheck)
1474          {
1475          Error("Missed a player sync check time=%ld\n",oldpolltime);
1476          }
1477       }
1478 }
1479 #endif
1480 
1481 //****************************************************************************
1482 //
1483 // ProcessSyncTimePacket
1484 //
1485 //****************************************************************************
1486 
ProcessSyncTimePacket(void * pkt)1487 void ProcessSyncTimePacket (void * pkt)
1488 {
1489    COM_SyncType * sync;
1490 
1491    sync=(COM_SyncType *)pkt;
1492    ISR_SetTime(sync->synctime);
1493 }
1494 
1495 #if (SYNCCHECK == 1)
1496 //****************************************************************************
1497 //
1498 // ProcessSyncCheckPacket
1499 //
1500 //****************************************************************************
1501 
ProcessSyncCheckPacket(void * pkt,int src)1502 void ProcessSyncCheckPacket (void * pkt, int src)
1503 {
1504    COM_CheckSyncType * sync;
1505 
1506    sync=(COM_CheckSyncType *)pkt;
1507 //   SoftError("Sync packet time=%ld\n",sync->synctime);
1508    if (sync->synctime!=PlayerSync[0].synctime)
1509       {
1510       SoftError("Old sync packet received\n");
1511       return;
1512       }
1513    if (sync->randomindex!=PlayerSync[0].randomindex)
1514       {
1515       Error("Player %ld is unsynced localindex=%ld remoteindex=%ld\n"
1516             "Unsynced Player x=%x y=%x a=%ld z=%ld name=%s\n",
1517              src, PlayerSync[0].randomindex, sync->randomindex,
1518              PlayerSync[src].x, PlayerSync[src].y, PlayerSync[src].angle,
1519              PlayerSync[src].z,PLAYERSTATE[src].codename);
1520       }
1521    if (sync->x!=PlayerSync[src].x)
1522       {
1523       Error("Player %ld is unsynced local x=%ld remote x=%ld\n"
1524             "Unsynced Player x=%x y=%x a=%ld z=%ld name=%s\n",
1525              src,PlayerSync[src].x,sync->x,
1526              PlayerSync[src].x, PlayerSync[src].y, PlayerSync[src].angle,
1527              PlayerSync[src].z,PLAYERSTATE[src].codename);
1528       }
1529    if (sync->y!=PlayerSync[src].y)
1530       {
1531       Error("Player %ld is unsynced local y=%ld remote y=%ld\n"
1532             "Unsynced Player x=%x y=%x a=%ld z=%ld name=%s\n",
1533              src,PlayerSync[src].y,sync->y,
1534              PlayerSync[src].x, PlayerSync[src].y, PlayerSync[src].angle,
1535              PlayerSync[src].z,PLAYERSTATE[src].codename);
1536       }
1537    if (sync->z!=PlayerSync[src].z)
1538       {
1539       Error("Player %ld is unsynced local z=%ld remote z=%ld\n"
1540             "Unsynced Player x=%x y=%x a=%ld z=%ld name=%s\n",
1541              src,PlayerSync[src].z,sync->z,
1542              PlayerSync[src].x, PlayerSync[src].y, PlayerSync[src].angle,
1543              PlayerSync[src].z,PLAYERSTATE[src].codename);
1544       }
1545    if (sync->angle!=PlayerSync[src].angle)
1546       {
1547       Error("Player %ld is unsynced local angle=%ld remote angle=%ld\n"
1548             "Unsynced Player x=%x y=%x a=%ld z=%ld name=%s\n",
1549              src,PlayerSync[src].angle,sync->angle,
1550              PlayerSync[src].x, PlayerSync[src].y, PlayerSync[src].angle,
1551              PlayerSync[src].z,PLAYERSTATE[src].codename);
1552       }
1553 }
1554 
1555 //****************************************************************************
1556 //
1557 // SendSyncCheckPacket
1558 //
1559 //****************************************************************************
1560 
SendSyncCheckPacket(void)1561 void SendSyncCheckPacket ( void )
1562 {
1563    ((COM_CheckSyncType *)NextLocalCommand())->type=COM_SYNCCHECK;
1564    ((COM_CheckSyncType *)NextLocalCommand())->synctime=PlayerSync[0].synctime;
1565    ((COM_CheckSyncType *)NextLocalCommand())->x=PlayerSync[consoleplayer].x;
1566 	((COM_CheckSyncType *)NextLocalCommand())->y=PlayerSync[consoleplayer].y;
1567 	((COM_CheckSyncType *)NextLocalCommand())->z=PlayerSync[consoleplayer].z;
1568 	((COM_CheckSyncType *)NextLocalCommand())->angle=PlayerSync[consoleplayer].angle;
1569 	((COM_CheckSyncType *)NextLocalCommand())->randomindex=PlayerSync[0].randomindex;
1570 
1571    PrepareLocalPacket();
1572 }
1573 #endif
1574 
1575 #if 0
1576 
1577 //****************************************************************************
1578 //
1579 // CheckForSyncTime
1580 //
1581 //****************************************************************************
1582 
1583 void CheckForSyncTime ( void )
1584 {
1585    if ((modemgame==true) && (networkgame==false) && (consoleplayer==0))
1586       {
1587       if (controlupdatetime>=syncservertime)
1588          {
1589          SendSyncTimePacket();
1590          syncservertime+=MODEMSYNCSERVERTIME;
1591          }
1592       }
1593 }
1594 #endif
1595 
1596 #if 0
1597 //****************************************************************************
1598 //
1599 // SendSyncTimePacket
1600 //
1601 //****************************************************************************
1602 
1603 void SendSyncTimePacket ( void )
1604 {
1605    int i;
1606    COM_SyncType sync;
1607 
1608    return;
1609 
1610    sync.type=COM_SYNCTIME;
1611 
1612    if (networkgame==true)
1613       {
1614       for (i=0;i<numplayers;i++)
1615          {
1616          if ((PlayerStatus[i]!=player_ingame) || ( (i==consoleplayer) && (standalone==false) ) )
1617             continue;
1618          sync.synctime=GetTicCount()+GetTransitTime(i);
1619          WritePacket ( &sync.type, GetPacketSize(&sync.type), i);
1620          }
1621       }
1622    else
1623       {
1624       if (PlayerStatus[server]==player_ingame)
1625          {
1626          sync.synctime=GetTicCount()+GetTransitTime(server);
1627          WritePacket ( &sync.type, GetPacketSize(&sync.type), server);
1628          }
1629       }
1630 }
1631 #endif
1632 
1633 //****************************************************************************
1634 //
1635 // ProcessSoundAndDeltaPacket
1636 //
1637 //****************************************************************************
1638 
ProcessSoundAndDeltaPacket(void * pkt,int src)1639 void ProcessSoundAndDeltaPacket (void * pkt, int src)
1640 {
1641    MoveType * packet;
1642    COM_SoundType * sndpkt;
1643    byte oldtype;
1644 
1645    packet = (MoveType *)pkt;
1646 
1647    // Trick packet into being a normal delta packet
1648 
1649    oldtype=packet->type;
1650    packet->type=COM_DELTA;
1651    AddClientPacket (pkt,src);
1652    packet->type=oldtype;
1653 
1654    // Don't process sound if it is from us
1655    if (src==consoleplayer)
1656       return;
1657 
1658    sndpkt = (COM_SoundType *) (packet->Sounddata);
1659 
1660    if (sndpkt->type==COM_SOUND_START_TRANSMISSION)
1661       {
1662       SD_StartIncomingSound ();
1663       }
1664    if (sndpkt->type==COM_SOUND_END_TRANSMISSION)
1665       {
1666       SD_StopIncomingSound();
1667       }
1668    else
1669       {
1670       SD_UpdateIncomingSound (&(sndpkt->data[0]), COM_SOUND_BUFFERSIZE);
1671       }
1672 }
1673 //****************************************************************************
1674 //
1675 // SyncToServer
1676 //
1677 //****************************************************************************
1678 #define NETWORKTIMEAHEADOFSERVER (1)
1679 #define MODEMTIMEAHEADOFSERVER (2)
SyncToServer(void)1680 void SyncToServer( void )
1681 {
1682    int diff;
1683 
1684    if ((networkgame==false) && (consoleplayer==0))
1685       return;
1686    if (IsServer==true)
1687       return;
1688 //   if (networkgame==true)
1689 //      {
1690 //      diff = (GetTicCount()-controldivisor-LastCommandTime[0])/controldivisor;
1691 //      SoftError("diff=%ld\n",diff);
1692 //      if (abs(diff)>1)
1693 //         ISR_SetTime(GetTicCount()-diff);
1694 #if 0
1695       diff = controlupdatetime-LastCommandTime[0];
1696       if (diff>3)
1697          {
1698          ISR_SetTime(GetTicCount()-1);
1699          }
1700       else if (diff<-3)
1701          {
1702          ISR_SetTime(GetTicCount()+1);
1703          }
1704 #endif
1705 //      }
1706 //   else
1707 //      {
1708       diff = (GetTicCount()-controldivisor-LastCommandTime[server])/controldivisor;
1709       if (abs(diff)>0)
1710          ISR_SetTime(GetTicCount()-diff);
1711 //      }
1712 }
1713 
1714 //****************************************************************************
1715 //
1716 // ProcessPacket
1717 //
1718 //****************************************************************************
1719 
ProcessPacket(void * pkt,int src)1720 void ProcessPacket (void * pkt, int src)
1721 {
1722    switch (((MoveType *)pkt)->type)
1723       {
1724       case COM_DELTA:
1725       case COM_DELTANULL:
1726       case COM_TEXT:
1727       case COM_PAUSE:
1728       case COM_QUIT:
1729       case COM_EXIT:
1730       case COM_REMRID:
1731       case COM_RESPAWN:
1732       case COM_UNPAUSE:
1733       case COM_ENDGAME:
1734 #if (SYNCCHECK == 1)
1735       case COM_SYNCCHECK:
1736 #endif
1737 //         if (FixingPackets==false)
1738          AddPacket(pkt,src);
1739          break;
1740       case COM_SOUNDANDDELTA:
1741          if (remoteridicule == false )
1742             {
1743             ((MoveType *)pkt)->type = COM_DELTA;
1744             }
1745          AddPacket(pkt,src);
1746          break;
1747       case COM_SERVER:
1748          AddServerPacket(pkt,src);
1749          break;
1750 
1751       case COM_REQUEST:
1752          ResendPacket(pkt, src);
1753          break;
1754 
1755       case COM_FIXUP:
1756          FixupPacket(pkt, src);
1757          break;
1758 
1759       case COM_SYNCTIME:
1760          ProcessSyncTimePacket(pkt);
1761          break;
1762 
1763       case COM_GAMEEND:
1764       case COM_GAMEDESC:
1765       case COM_GAMEACK:
1766       case COM_GAMEMASTER:
1767          if (standalone==true)
1768             restartgame=true;
1769          break;
1770 
1771       case COM_START:
1772          break;
1773 
1774       default:
1775          Error("ProcessPacket: Unknown packet type=%ld\n",((MoveType *)pkt)->type);
1776       }
1777 }
1778 
1779 
1780 //****************************************************************************
1781 //
1782 // AddServerSubPacket
1783 //
1784 //****************************************************************************
1785 
AddServerSubPacket(COM_ServerHeaderType * serverpkt)1786 void AddServerSubPacket(COM_ServerHeaderType * serverpkt)
1787 {
1788    byte * pkt;
1789    int i;
1790 
1791    ServerCommandStatus(serverpkt->time)=cs_ready;
1792 
1793    pkt=&serverpkt->data;
1794    for (i=0;i<serverpkt->numpackets;i++)
1795       {
1796       AddClientPacket(pkt,i);
1797       pkt+=GetPacketSize(pkt);
1798       }
1799 }
1800 
1801 //****************************************************************************
1802 //
1803 // AddModemSubPacket
1804 //
1805 //****************************************************************************
1806 
AddModemSubPacket(void * incoming)1807 void AddModemSubPacket(void * incoming)
1808 {
1809    MoveType * pkt;
1810 
1811    pkt=(MoveType *)incoming;
1812    ServerCommandStatus(pkt->time)=cs_ready;
1813 
1814    AddClientPacket(incoming,server);
1815 }
1816 
1817 //****************************************************************************
1818 //
1819 // AddServerPacket
1820 //
1821 //****************************************************************************
1822 
AddServerPacket(void * pkt,int src)1823 void AddServerPacket(void * pkt, int src)
1824 {
1825    COM_ServerHeaderType * serverpkt;
1826 
1827    // The server uses the client's lgts for communicating
1828 
1829    // Last good time can be set even for the client/server combo
1830 
1831    if (standalone==true)
1832       {
1833       Error("standalone should not be here\n");
1834       }
1835 
1836    if (src!=server)
1837       {
1838       Error("Received server packet from non-server src=%ld\n",src);
1839       }
1840 
1841    serverpkt=(COM_ServerHeaderType *)pkt;
1842 
1843 //   if (networkgame==false)
1844 //      SyncToServer(serverpkt->time);
1845 
1846    LastCommandTime[src]+=controldivisor;
1847 
1848    if (serverpkt->time != LastCommandTime[src])
1849       {
1850       int numpackets;
1851 
1852       numpackets=serverpkt->time-LastCommandTime[src];
1853       if (ServerCommandStatus(LastCommandTime[src])!=cs_fixing)
1854          {
1855          RequestPacket ( LastCommandTime[src] , src , numpackets );
1856 
1857          ComError("AddServerPacket: Request packet time=%ld lct=%ld numpackets=%ld\n",
1858                   serverpkt->time, LastCommandTime[src], numpackets
1859                  );
1860          }
1861 
1862       LastCommandTime[src]+=numpackets;
1863       }
1864 
1865    AddServerSubPacket( serverpkt );
1866 }
1867 
1868 //****************************************************************************
1869 //
1870 // AddClientPacket
1871 //
1872 //****************************************************************************
1873 
AddClientPacket(void * pkt,int src)1874 void AddClientPacket (void * pkt, int src)
1875 {
1876    int size;
1877    MoveType * packet;
1878 
1879    packet=(MoveType *)pkt;
1880 
1881    switch (packet->type)
1882       {
1883       case COM_DELTA:
1884       case COM_DELTANULL:
1885       case COM_TEXT:
1886       case COM_REMRID:
1887       case COM_PAUSE:
1888       case COM_QUIT:
1889       case COM_EXIT:
1890       case COM_RESPAWN:
1891       case COM_UNPAUSE:
1892 #if (SYNCCHECK == 1)
1893       case COM_SYNCCHECK:
1894 #endif
1895       case COM_ENDGAME:
1896          size=GetPacketSize(packet);
1897          memcpy(PlayerCommand(src,CommandAddress(packet->time)),packet,size);
1898          break;
1899       case COM_SOUNDANDDELTA:
1900          ProcessSoundAndDeltaPacket(packet, src);
1901          break;
1902       default:
1903          Error("AddClientPacket: Unknown packet type = %ld\n",packet->type);
1904       }
1905 }
1906 
1907 //****************************************************************************
1908 //
1909 // AddSubPacket
1910 //
1911 //****************************************************************************
1912 
AddSubPacket(void * pkt,int src)1913 void AddSubPacket (void * pkt, int src)
1914 {
1915    MoveType * packet;
1916 
1917    if (networkgame==false)
1918       Error("Modem game should not be here in AddSubPacket\n");
1919 
1920    packet = (MoveType *) pkt;
1921 
1922    ClientCommandStatus(src, packet->time)=cs_ready;
1923 
1924    memcpy (
1925           ClientTimeCommand(src,packet->time),
1926           pkt,
1927           GetPacketSize(packet)
1928           );
1929 }
1930 
1931 //****************************************************************************
1932 //
1933 // AddPacket
1934 //
1935 //****************************************************************************
1936 
AddPacket(void * pkt,int src)1937 void AddPacket (void * pkt, int src)
1938 {
1939    MoveType * packet;
1940 
1941    // should only be called by server in network game
1942    // in modem game we fall through the first condition
1943    // all packets should be sequential
1944 
1945    if ((IsServer==true) && (PlayerStatus[src]!=player_ingame))
1946       return;
1947    packet = (MoveType *) pkt;
1948 
1949 //   if ((networkgame==false) && (consoleplayer!=0))
1950 //      SyncToServer();
1951 
1952    if (!((src==server) && (standalone==false) && (IsServer==true)))
1953       {
1954       LastCommandTime[src]+=controldivisor;
1955 
1956       if (packet->time != LastCommandTime[src])
1957          {
1958          int numpackets;
1959 
1960          numpackets=packet->time-LastCommandTime[src];
1961          if ( ( (networkgame==false) &&
1962                (ServerCommandStatus(LastCommandTime[src])!=cs_fixing)
1963             )
1964             ||
1965             ( (networkgame==true) &&
1966                (ClientCommandStatus(src,LastCommandTime[src])!=cs_fixing)
1967             )
1968             )
1969             {
1970             RequestPacket ( LastCommandTime[src] , src , numpackets );
1971 
1972             ComError("AddPacket: Request packet time=%ld lct=%ld numpackets=%ld\n",
1973                      packet->time, LastCommandTime[src], numpackets
1974                      );
1975             }
1976 
1977          LastCommandTime[src]+=numpackets;
1978          }
1979       }
1980 
1981    if (networkgame==true)
1982       {
1983       AddSubPacket ( packet, src );
1984       }
1985    else
1986       {
1987       AddModemSubPacket(packet);
1988       }
1989 }
1990 
1991 
1992 //****************************************************************************
1993 //
1994 // RequestPacket ( int time, int dest )
1995 //
1996 //****************************************************************************
1997 
RequestPacket(int time,int dest,int numpackets)1998 void RequestPacket (int time, int dest, int numpackets)
1999 {
2000    COM_RequestType request;
2001    int i;
2002 
2003 
2004 #if (DEVELOPMENT == 1)
2005    if (modemgame==false)
2006       Error("Called Request Packet outside of modem game\n");
2007 #endif
2008 
2009    request.type=COM_REQUEST;
2010    request.time=time;
2011    request.numpackets=numpackets/controldivisor;
2012 
2013    if (IsServer==true)
2014       {
2015       if ((dest==server) && (standalone==false))
2016          {
2017          Error("Requesting packet from client on top of server\n");
2018          }
2019       if (PlayerStatus[dest]!=player_ingame)
2020          return;
2021       for (i=0;i<numpackets;i+=controldivisor)
2022          {
2023          ClientCommandStatus( dest , (time+i) ) = cs_fixing;
2024          }
2025       }
2026    else
2027       {
2028       if ((networkgame==false) && (PlayerStatus[dest]!=player_ingame))
2029          return;
2030       for (i=0;i<numpackets;i+=controldivisor)
2031          {
2032          ServerCommandStatus( (time+i) ) = cs_fixing;
2033          }
2034       }
2035 //   if (networkgame==false)
2036 //      FixingPackets=true;
2037 
2038    // send out the packet
2039 
2040    WritePacket (&request, GetPacketSize(&request), dest);
2041 
2042 #if (DEVELOPMENT == 1)
2043 //   ComError( "BADPKT, request sent at %ld lgt=%ld dest=%ld\n",GetTicCount(),time,dest);
2044 #endif
2045 }
2046 
2047 //****************************************************************************
2048 //
2049 // IsServerCommandReady ()
2050 //
2051 //****************************************************************************
IsServerCommandReady(int time)2052 boolean IsServerCommandReady ( int time )
2053 {
2054 
2055    if (
2056        (
2057         (COM_ServerHeaderType *)
2058          ServerCommand(CommandAddress (time) ) )->time==time)
2059       return true;
2060    else
2061       {
2062       return false;
2063       }
2064 }
2065 
2066 //****************************************************************************
2067 //
2068 // AreClientsReady ()
2069 //
2070 //****************************************************************************
AreClientsReady(void)2071 boolean AreClientsReady ( void )
2072 {
2073    int i;
2074    int timeindex;
2075    int status;
2076 
2077    timeindex=CommandAddress(serverupdatetime);
2078 
2079 	for (i=0;i<numplayers;i++)
2080       {
2081       if (PlayerStatus[i]!=player_ingame)
2082          continue;
2083       status=ClientCommandStatus(i, serverupdatetime);
2084       if (status==cs_notarrived)
2085          return false;
2086       else if (status==cs_fixing)
2087          {
2088 //         RequestPacket ( serverupdatetime , i , controldivisor );
2089          return false;
2090          }
2091       else if (((MoveType *)ClientCommand(i, timeindex))->time != serverupdatetime)
2092          return false;
2093       }
2094    return true;
2095 }
2096 
2097 //****************************************************************************
2098 //
2099 // IsPlayerCommandReady ()
2100 //
2101 //****************************************************************************
IsPlayerCommandReady(int num,int time)2102 boolean IsPlayerCommandReady (int num, int time)
2103 {
2104    MoveType * cmd;
2105 
2106    cmd=(MoveType *)PlayerCommand(num,CommandAddress(time));
2107 
2108    if (cmd->time==time)
2109       return true;
2110    else
2111       return false;
2112 }
2113 
2114 //****************************************************************************
2115 //
2116 // ResetClientCommands ()
2117 //
2118 //****************************************************************************
ResetClientCommands(int player)2119 void ResetClientCommands ( int player )
2120 {
2121    int j;
2122 
2123    for (j=0;j<MAXCMDS;j++)
2124       {
2125       memset(ClientCommand(player,j),COM_DELTA,GamePacketSize());
2126       }
2127 }
2128 
2129 //****************************************************************************
2130 //
2131 // SendFullServerPacket ()
2132 //
2133 //****************************************************************************
SendFullServerPacket(void)2134 void SendFullServerPacket ( void )
2135 {
2136    int i;
2137    int size;
2138    byte * pkt;
2139    COM_ServerHeaderType * spkt;
2140    int timeindex;
2141    int playerstatus[MAXPLAYERS];
2142 
2143    timeindex=CommandAddress(serverupdatetime);
2144 
2145    spkt=(COM_ServerHeaderType *)ServerCommand(timeindex);
2146 
2147    pkt=&spkt->data;
2148    spkt->time=serverupdatetime;
2149    spkt->type=COM_SERVER;
2150 	spkt->numpackets=numplayers;
2151 
2152 
2153    memset(playerstatus,-1,sizeof(playerstatus));
2154 	for (i=0;i<numplayers;i++)
2155       {
2156       size=GetPacketSize(ClientCommand(i,timeindex));
2157       if (((MoveType *)ClientCommand(i,timeindex))->type == COM_QUIT)
2158          {
2159          playerstatus[i]=player_quitgame;
2160          }
2161       if (((MoveType *)ClientCommand(i,timeindex))->type == COM_ENDGAME)
2162          {
2163          playerstatus[i]=player_leftgame;
2164          }
2165       memcpy(pkt,
2166             ClientCommand(i,timeindex),
2167             size
2168             );
2169       pkt+=size;
2170       ClientCommandNumberStatus(i,timeindex)=cs_notarrived;
2171       }
2172    BroadcastServerPacket((void *)spkt,(pkt-(byte *)spkt));
2173    serverupdatetime+=controldivisor;
2174 
2175    for (i=0;i<numplayers;i++)
2176       {
2177       if (playerstatus[i]!=-1)
2178          {
2179          if ((standalone==false) && (consoleplayer==i))
2180             {
2181             UpdateServer=false;
2182             }
2183          else
2184             {
2185             ResetClientCommands(i);
2186             PlayerStatus[i]=playerstatus[i];
2187             }
2188          }
2189       }
2190 }
2191 
2192 
2193 
2194 //****************************************************************************
2195 //
2196 // ProcessServer ()
2197 //
2198 //****************************************************************************
2199 
ProcessServer(void)2200 void ProcessServer ( void )
2201 {
2202    boolean done;
2203    boolean exit;
2204    int i;
2205    int time;
2206    int quittime;
2207 
2208    if (InProcessServer==true)
2209       return;
2210 
2211    InProcessServer=true;
2212 
2213    if (GetTicCount()<serverupdatetime)
2214       goto exitProcessServer;
2215 
2216    time=GetTicCount();
2217    quittime=GetTicCount()+SERVERTIMEOUT;
2218    exit=false;
2219 
2220    while (time>=serverupdatetime)
2221       {
2222       int savetime;
2223 
2224       savetime=GetTicCount()+NETWORKTIMEOUT;
2225       done = false;
2226 		while (done == false)
2227          {
2228          if (standalone==true)
2229             AbortCheck("GameServer aborted\n");
2230 
2231          done = AreClientsReady ();
2232 
2233          if ( (standalone==false) && (serverupdatetime>=(controlupdatetime-controldivisor)) && (done==false) )
2234             break;
2235 
2236          CheckForPacket ();
2237 
2238          if (standalone==false)
2239             UpdateClientControls();
2240 
2241          if (restartgame==true)
2242             break;
2243          if (GetTicCount()>savetime)
2244             {
2245             for (i=0;i<numplayers;i++)
2246                {
2247                int val;
2248 
2249                val=ClientCommandStatus(i, serverupdatetime);
2250                if ((val!=cs_ready) && (PlayerStatus[i]==player_ingame))
2251                   {
2252                   SoftError("Server timeout\n");
2253                   RequestPacket(serverupdatetime, i , controldivisor);
2254                   }
2255                }
2256             savetime=GetTicCount()+NETWORKTIMEOUT;
2257             }
2258 //         if (GetTicCount()>quittime)
2259 //            {
2260 //            Error("Server aborting after %ld seconds\n",SERVERTIMEOUT/VBLCOUNTER);
2261 //            }
2262          if ((standalone==false) && (done==false))
2263             {
2264             exit=true;
2265             done=true;
2266             }
2267          }
2268       if (exit==true)
2269          break;
2270       if ( (serverupdatetime>=(controlupdatetime-controldivisor)) && (standalone==false))
2271          break;
2272       if (restartgame==true)
2273          break;
2274       SendFullServerPacket();
2275 #if 0
2276       if (serverupdatetime>=syncservertime)
2277          {
2278          SendSyncTimePacket();
2279          syncservertime+=NETSYNCSERVERTIME;
2280          }
2281 #endif
2282       }
2283 exitProcessServer:
2284    InProcessServer=false;
2285 }
2286 
2287 
2288 //****************************************************************************
2289 //
2290 // SetupCheckForPacket()
2291 //
2292 //****************************************************************************
SetupCheckForPacket(void)2293 int SetupCheckForPacket ( void )
2294 {
2295    int retval=scfp_nodata;
2296 
2297    if ((ReadPacket()==true) && (badpacket==0))
2298       {
2299       MoveType * pkt;
2300 
2301       retval=scfp_data;
2302       pkt=(MoveType *)&ROTTpacket[0];
2303       if ((IsServer==true) && (standalone==true))
2304          {
2305          switch (pkt->type)
2306             {
2307             case COM_GAMEEND:
2308                break;
2309             case COM_GAMEDESC:
2310                if (standalone==true)
2311                   printf("Received GameDescription from player#%ld\n",(long int)rottcom->remotenode);
2312                WritePacket(&ROTTpacket[0],GetPacketSize(pkt),0); // Send to player 0
2313                break;
2314             case COM_GAMEACK:
2315                if (standalone==true)
2316                   printf("Received GameAcknowledgement from player#%ld\n",(long int)rottcom->remotenode);
2317                WritePacket(&ROTTpacket[0],GetPacketSize(pkt),0); // Send to player 0
2318                break;
2319             case COM_GAMEMASTER:
2320                if (standalone==true)
2321                   printf("Received GameMasterPacket from player#%ld\n",(long int)rottcom->remotenode);
2322                BroadcastServerPacket(&ROTTpacket[0],GetPacketSize(pkt)); // Send to all
2323                break;
2324             case COM_GAMEPLAY:
2325                if (standalone==true)
2326                   printf("Received StartGamePacket from player#%ld\n",(long int)rottcom->remotenode);
2327                BroadcastServerPacket(&ROTTpacket[0],GetPacketSize(pkt)); // Send to all
2328                retval=scfp_done;
2329                break;
2330             default:
2331                ComError("Server received unknown packet in Game preamble\n");
2332                break;
2333             }
2334          }
2335       else
2336          {
2337          switch (pkt->type)
2338             {
2339             case COM_GAMEPLAY:
2340                 retval=scfp_done;
2341                 break;
2342             case COM_GAMEMASTER:
2343                 SetGameDescription(pkt);
2344                 retval=scfp_gameready;
2345                 break;
2346             case COM_GAMEACK:
2347 					 PlayersReady[((COM_GameAckType *)pkt)->player]=true;
2348                 break;
2349             case COM_GAMEDESC:
2350 					 GotPlayersDesc[((COM_GamePlayerType *)pkt)->player]=true;
2351                 SetPlayerDescription(pkt);
2352                 break;
2353             }
2354          }
2355       }
2356    return retval;
2357 }
2358 
2359 
2360 //****************************************************************************
2361 //
2362 // ServerLoop ()
2363 //
2364 //****************************************************************************
ServerLoop(void)2365 void ServerLoop( void )
2366 {
2367    boolean done;
2368 
2369    while (1)
2370       {
2371       ShutdownClientControls();
2372       restartgame=false;
2373 
2374       done=false;
2375       while (done==false)
2376          {
2377          AbortCheck("SetupGameServer aborted\n");
2378 
2379          if (SetupCheckForPacket()==scfp_done)
2380             done=true;
2381          }
2382       ComSetTime();
2383       StartupClientControls();
2384       while(1)
2385          {
2386          ProcessServer();
2387 #if (DEVELOPMENT == 1)
2388          Z_CheckHeap();
2389 #endif
2390          CalcTics();
2391          if (restartgame==true)
2392             break;
2393          }
2394       }
2395 }
2396 
2397 //****************************************************************************
2398 //
2399 // ProcessPlayerCommand()
2400 //
2401 //****************************************************************************
ProcessPlayerCommand(int player)2402 void ProcessPlayerCommand( int player )
2403 {
2404    MoveType * cmd;
2405 
2406    cmd=(MoveType *)PlayerCommand(player,CommandAddress(oldpolltime));
2407 
2408 	if (cmd->type==COM_DELTA)
2409       {
2410 		UpdatePlayerObj(player);
2411       }
2412 	else if (cmd->type==COM_RESPAWN)
2413       {
2414 		if (player==consoleplayer) // reset spawn state
2415          respawnactive=false;
2416       RespawnPlayerobj(PLAYER[player]);
2417       }
2418 	else if (cmd->type==COM_ENDGAME)
2419       {
2420       playstate = ex_battledone;
2421       }
2422    else if (cmd->type==COM_QUIT)
2423       {
2424       if (player==consoleplayer)
2425          QuitGame();
2426       else
2427          {
2428          char str[50]="Player #";
2429          char str2[10];
2430 
2431          strcat(str,itoa(player+1,str2,10));
2432          strcat(str,", ");
2433          strcat(str,PLAYERSTATE[player].codename);
2434          strcat(str," has left the game.");
2435          AddMessage(str,MSG_REMOTE);
2436          PlayerStatus[player]=player_quitgame;
2437          }
2438       }
2439    else if (cmd->type==COM_EXIT)
2440       {
2441       QuitGame();
2442       }
2443    else if (cmd->type==COM_REMRID)
2444       {
2445       ProcessRemoteRidicule (cmd);
2446       }
2447    else if (cmd->type==COM_TEXT)
2448       {
2449       int who;
2450 
2451       who = ( ( COM_TextType * )cmd )->towho;
2452       if ( ( who == consoleplayer ) ||
2453          ( who == MSG_DIRECTED_TO_ALL ) ||
2454          ( ( who == MSG_DIRECTED_TO_TEAM ) &&
2455          ( BATTLE_Team[ player ] == BATTLE_Team[ consoleplayer ] ) ) )
2456          {
2457          char string[ 50 ];
2458 
2459          strcpy( string, "\\N9" );
2460          strcat( string, PLAYERSTATE[player].codename );
2461          strcat( string, ":\\NF" );
2462          strcat( string, ((COM_TextType *)cmd)->string );
2463          SD_PlayPitchedSound ( SD_ENDBONUS1SND, 255, 1200 );
2464 
2465          AddMessage( string, MSG_REMOTE );
2466          }
2467       }
2468 #if (SYNCCHECK == 1)
2469 	else if (cmd->type==COM_SYNCCHECK)
2470       {
2471       ProcessSyncCheckPacket(cmd, player);
2472       }
2473 #endif
2474 	else if (cmd->type==COM_PAUSE)
2475       {
2476       MUSIC_Pause();
2477       GamePaused=true;
2478       pausedstartedticcount = oldpolltime;
2479       }
2480 	else if (cmd->type==COM_UNPAUSE)
2481       {
2482       GamePaused=false;
2483       MUSIC_Continue ();
2484       if (RefreshPause == false)       // screen is blanked
2485          {
2486          ShutdownScreenSaver();
2487          SetupScreen (true);
2488          RefreshPause = true;
2489          }
2490       }
2491 }
2492 
2493 //****************************************************************************
2494 //
2495 // CheckUnPause ()
2496 //
2497 //****************************************************************************
CheckUnPause(void)2498 void CheckUnPause ( void )
2499 {
2500    if (oldpolltime==nextupdatetime)
2501       {
2502       nextupdatetime=oldpolltime+controldivisor;
2503       while (1)
2504          {
2505          if (ServerCommandStatus(oldpolltime)==cs_ready)
2506             {
2507             int j;
2508 
2509             for (j=0;j<numplayers;j++)
2510                {
2511                if (PlayerStatus[j]==player_ingame)
2512                   ProcessPlayerCommand( j );
2513                }
2514             break;
2515             }
2516          else
2517             {
2518             UpdateClientControls();
2519             }
2520          }
2521       }
2522 }
2523 
2524 
2525 //****************************************************************************
2526 //
2527 // ControlPlayerObj ()
2528 //
2529 //****************************************************************************
ControlPlayerObj(objtype * ob)2530 void ControlPlayerObj (objtype * ob)
2531 {
2532 	playertype * pstate;
2533    int num;
2534    int savetime;
2535 //   boolean asked;
2536 
2537 //   if (GamePaused==true)
2538 //      return;
2539 
2540    M_LINKSTATE(ob,pstate);
2541 
2542 	// get player number
2543 
2544    num=ob->dirchoosetime;
2545 
2546    memcpy (pstate->buttonheld, pstate->buttonstate, sizeof(pstate->buttonstate));
2547 
2548    if (oldpolltime==nextupdatetime)
2549       {
2550       if (num==numplayers-1)
2551          nextupdatetime=oldpolltime+controldivisor;
2552       if (networkgame==true)
2553          savetime=GetTicCount()+NETWORKTIMEOUT;
2554       else
2555          savetime=GetTicCount()+MODEMTIMEOUT;
2556 
2557       if (PlayerStatus[num]!=player_ingame)
2558          return;
2559 
2560       //   asked=false;
2561 
2562       // copy previous state of buttons
2563 
2564 
2565       while (1)
2566          {
2567          if (ServerCommandStatus(oldpolltime)==cs_ready)
2568             {
2569             ProcessPlayerCommand (num);
2570             if (demoplayback||demorecord) {
2571                SoftError("x=%4lx y=%4lx a=%4lx time=%5ld\n",player->x,player->y,player->angle,oldpolltime);
2572 	    }
2573             break;
2574             }
2575    //      else if ((ServerCommandStatus(oldpolltime)==cs_fixing) &&
2576    //               (networkgame==false) &&
2577    //               (asked==false)
2578    //              )
2579    //         {
2580    //         asked=true;
2581    //         RequestPacket(oldpolltime, server, controldivisor);
2582    //         }
2583          else
2584             {
2585             UpdateClientControls();
2586             }
2587 
2588          if (GetTicCount()>savetime)
2589             {
2590             SoftError("Client timeout oldpolltime=%ld\n",oldpolltime);
2591             if (IsServer==false)
2592                RequestPacket(oldpolltime, server, controldivisor);
2593             if (networkgame==true)
2594                savetime=GetTicCount()+NETWORKTIMEOUT;
2595             else
2596                savetime=GetTicCount()+MODEMTIMEOUT;
2597             }
2598          }
2599       }
2600 
2601    if (!(ob->flags&FL_DYING))
2602       {
2603       if (ob->flags&FL_PUSHED)
2604          {
2605          ob->flags&=~FL_PUSHED;
2606 #if 0
2607          if (abs(ob->momentumx)>0)
2608             {
2609             if (abs(ob->momentumx+pstate->dmomx)>=abs(ob->momentumx))
2610                {
2611                ob->momentumx += pstate->dmomx;
2612                ob->momentumy += pstate->dmomy;
2613                }
2614             }
2615          else if (abs(ob->momentumy+pstate->dmomy)>=abs(ob->momentumy))
2616             {
2617             ob->momentumx += pstate->dmomx;
2618             ob->momentumy += pstate->dmomy;
2619             }
2620 #endif
2621          if (abs(ob->momentumx+pstate->dmomx)>=abs(ob->momentumx))
2622             {
2623             ob->momentumx += pstate->dmomx;
2624             }
2625          if (abs(ob->momentumy+pstate->dmomy)>=abs(ob->momentumy))
2626             {
2627             ob->momentumy += pstate->dmomy;
2628             }
2629          }
2630       else
2631          {
2632          ob->momentumx += pstate->dmomx;
2633          ob->momentumy += pstate->dmomy;
2634          }
2635       }
2636 }
2637 
2638 //****************************************************************************
2639 //
2640 // MaxSpeedForCharacter ()
2641 //
2642 //****************************************************************************
2643 
MaxSpeedForCharacter(playertype * pstate)2644 int MaxSpeedForCharacter(playertype*pstate)
2645 {
2646    if (BATTLEMODE && (gamestate.BattleOptions.Speed == bo_fast_speed))
2647       {
2648       return( FASTSPEED );
2649       }
2650    else
2651       {
2652       if (pstate->buttonstate[bt_run])
2653          return (characters[pstate->player].toprunspeed);
2654       else
2655          return (characters[pstate->player].topspeed);
2656       }
2657 }
2658 
2659 //****************************************************************************
2660 //
2661 // UpdatePlayerObj ()
2662 //
2663 //****************************************************************************
2664 
UpdatePlayerObj(int player)2665 void UpdatePlayerObj ( int player )
2666 {
2667 	int i, buttonbits;
2668 	playertype * pstate;
2669 	MoveType * MoveCmd;
2670 
2671    MoveCmd=(MoveType *)PlayerCommand(player,CommandAddress(oldpolltime));
2672 
2673 	pstate=&PLAYERSTATE[player];
2674 
2675    buttonbits = MoveCmd->buttons;
2676 	for (i = 0; i < NUMTXBUTTONS; i++)
2677 		{
2678 		pstate->buttonstate[i] = buttonbits & 1;
2679 		buttonbits   >>= 1;
2680 		}
2681 
2682    pstate->dmomx = (int)(MoveCmd->momx)<<1;
2683    pstate->dmomy = (int)(MoveCmd->momy)<<1;
2684 	pstate->angle = MoveCmd->dangle;
2685 	pstate->angle <<= 11;
2686    pstate->topspeed=MaxSpeedForCharacter(pstate);
2687 
2688    if (demoplayback||demorecord) {
2689       SoftError("  dmx=%4lx dmy=%4lx da=%4lx time=%5ld\n",pstate->dmomx,pstate->dmomy,pstate->angle>>11,oldpolltime);
2690    }
2691 #if 0
2692 #if (DEVELOPMENT == 1)
2693          if ((modemgame==true) || (demoplayback==true) || (demorecord==true))
2694 		   {
2695 			ComError( "player#%2ld\n",player);
2696 		   ComError( "momx = %6ld\n", PLAYER[player]->momentumx);
2697 		   ComError( "momy = %6ld\n", PLAYER[player]->momentumy);
2698 		   ComError( "   x = %6ld\n", PLAYER[player]->x);
2699 		   ComError( "   y = %6ld\n", PLAYER[player]->y);
2700 		   ComError( "   z = %6ld\n", PLAYER[player]->z);
2701 		   ComError( "   a = %6ld\n", PLAYER[player]->angle);
2702 		   if (pstate->buttonstate[bt_attack])
2703 			   ComError( "FIRING\n");
2704          }
2705 #endif
2706 #endif
2707 }
2708 
2709 
2710 //****************************************************************************
2711 //
2712 // SendPlayerDescription ()
2713 //
2714 //****************************************************************************
2715 
SendPlayerDescription(void)2716 void SendPlayerDescription( void )
2717 {
2718    byte * temp;
2719    COM_GamePlayerType * desc;
2720    int length;
2721 
2722    length=sizeof(COM_GamePlayerType);
2723    temp=SafeMalloc(length);
2724 
2725    memset(temp,0,length);
2726 
2727    desc=(COM_GamePlayerType *)temp;
2728    desc->type=(byte)COM_GAMEDESC;
2729 	desc->player=consoleplayer;
2730    desc->violence=gamestate.violence;
2731    desc->Version = gamestate.Version;
2732    desc->Product = gamestate.Product;
2733    desc->playerdescription.character=locplayerstate->player;
2734    desc->playerdescription.uniformcolor=locplayerstate->uniformcolor;
2735    strcpy(&(desc->playerdescription.codename[0]),
2736       &locplayerstate->codename[0]);
2737 
2738    WritePacket(temp,length,server);
2739 
2740    SafeFree(temp);
2741 }
2742 
2743 //****************************************************************************
2744 //
2745 // SendGameDescription ()
2746 //
2747 //****************************************************************************
2748 
SendGameDescription(void)2749 void SendGameDescription( void )
2750 {
2751    byte * temp;
2752    COM_GameMasterType * desc;
2753    int length;
2754    int i;
2755 
2756    length=sizeof(COM_GameMasterType);
2757    temp=SafeMalloc(length);
2758 
2759    memset(temp,0,length);
2760 
2761    desc=(COM_GameMasterType *)temp;
2762    desc->type=(byte)COM_GAMEMASTER;
2763    desc->level=gamestate.mapon;
2764    desc->mapcrc=GetMapCRC (gamestate.mapon);
2765    desc->mode=gamestate.battlemode;
2766    desc->violence=gamestate.violence;
2767    desc->Version = gamestate.Version;
2768    desc->Product = gamestate.Product;
2769    desc->teamplay = gamestate.teamplay;
2770    memcpy( &desc->SpecialsTimes, &gamestate.SpecialsTimes, sizeof( specials ) );
2771    BATTLE_GetOptions( &( desc->options ) );
2772    GetMapFileName( &(desc->battlefilename[0]) );
2773    desc->randomseed=GetRNGindex ( );
2774    gamestate.randomseed=desc->randomseed;
2775    desc->ludicrousgibs=battlegibs;
2776    ludicrousgibs=battlegibs;
2777 //   SetRNGindex ( gamestate.randomseed );
2778 	for (i=0;i<numplayers;i++)
2779       {
2780       if (gamestate.Product == ROTT_SHAREWARE)
2781          PLAYERSTATE[i].player = 0;
2782 		desc->players[i].character    =PLAYERSTATE[i].player;
2783 		desc->players[i].uniformcolor =PLAYERSTATE[i].uniformcolor;
2784       strcpy ( &(desc->players[i].codename[0]),&(PLAYERSTATE[i].codename[0]));
2785       }
2786 
2787    if (!networkgame)
2788       AssignTeams();
2789 
2790    if (IsServer==false)
2791       {
2792       WritePacket(temp,length,server);
2793       }
2794    else
2795       {
2796       BroadcastServerPacket(temp,length); // Send to all
2797       }
2798 
2799    SafeFree(temp);
2800 }
2801 
2802 //****************************************************************************
2803 //
2804 // SetGameDescription ()
2805 //
2806 //****************************************************************************
2807 
SetGameDescription(void * pkt)2808 void SetGameDescription( void * pkt )
2809 {
2810    COM_GameMasterType * desc;
2811    word localcrc;
2812    int i;
2813 
2814    desc=(COM_GameMasterType *)pkt;
2815    gamestate.mapon=desc->level;
2816    gamestate.battlemode=desc->mode;
2817    gamestate.violence=desc->violence;
2818    gamestate.Version = desc->Version;
2819    gamestate.Product = desc->Product;
2820    gamestate.teamplay = desc->teamplay;
2821    memcpy( &gamestate.SpecialsTimes, &desc->SpecialsTimes, sizeof( specials ) );
2822    BATTLE_SetOptions( &( desc->options ) );
2823    gamestate.randomseed=desc->randomseed;
2824    SetRNGindex ( gamestate.randomseed );
2825    SetBattleMapFileName( &(desc->battlefilename[0]) );
2826    localcrc=GetMapCRC (gamestate.mapon);
2827    ludicrousgibs=desc->ludicrousgibs;
2828    if (localcrc!=desc->mapcrc)
2829       Error("You have different maps on your system\n");
2830    for (i=0;i<numplayers;i++)
2831       {
2832 		PLAYERSTATE[i].player=desc->players[i].character;
2833 		PLAYERSTATE[i].uniformcolor=desc->players[i].uniformcolor;
2834       strcpy ( &(PLAYERSTATE[i].codename[0]),
2835                &(desc->players[i].codename[0])
2836              );
2837       }
2838    AssignTeams();
2839 }
2840 
2841 //****************************************************************************
2842 //
2843 // SetPlayerDescription ()
2844 //
2845 //****************************************************************************
2846 
SetPlayerDescription(void * pkt)2847 void SetPlayerDescription( void * pkt )
2848 {
2849    COM_GamePlayerType * desc;
2850 
2851    desc=(COM_GamePlayerType *)pkt;
2852 	PLAYERSTATE[desc->player].player=desc->playerdescription.character;
2853    PLAYERSTATE[desc->player].uniformcolor=desc->playerdescription.uniformcolor;
2854    strcpy ( &(PLAYERSTATE[desc->player].codename[0]),
2855             &(desc->playerdescription.codename[0])
2856           );
2857    if ( gamestate.Version != desc->Version )
2858       {
2859       Error("Player %s is using a different version of ROTT\n",PLAYERSTATE[desc->player].codename);
2860 //      gamestate.Version = desc->Version;
2861       }
2862 
2863    if ( gamestate.violence > desc->violence )
2864       {
2865       gamestate.violence = desc->violence;
2866       }
2867 
2868    if ( gamestate.Product > desc->Product )
2869       {
2870       gamestate.Product = desc->Product;
2871       }
2872 }
2873 
2874 //****************************************************************************
2875 //
2876 // SendGameAck ()
2877 //
2878 //****************************************************************************
2879 
SendGameAck(void)2880 void SendGameAck( void )
2881 {
2882    byte * temp;
2883    int length;
2884    COM_GameAckType * desc;
2885 
2886    length=sizeof(COM_GameAckType);
2887    temp=SafeMalloc(length);
2888    desc=(COM_GameAckType *)temp;
2889    desc->type=COM_GAMEACK;
2890 	desc->player=consoleplayer;
2891 
2892    WritePacket(temp,length,server);
2893 
2894    SafeFree(temp);
2895 }
2896 
2897 //****************************************************************************
2898 //
2899 // SendGameStart ()
2900 //
2901 //****************************************************************************
2902 
SendGameStart(void)2903 void SendGameStart( void )
2904 {
2905    byte * temp;
2906    int length;
2907 
2908    length=DUMMYPACKETSIZE;
2909    temp=SafeMalloc(length);
2910    *(temp)=(byte)COM_GAMEPLAY;
2911 
2912    if (IsServer==false)
2913       {
2914       WritePacket(temp,length,server);
2915       }
2916    else
2917       {
2918       BroadcastServerPacket(temp,length); // Send to all
2919       }
2920 
2921    SafeFree(temp);
2922 }
2923 
2924 //****************************************************************************
2925 //
2926 // SetupGamePlayer ()
2927 //
2928 //****************************************************************************
SetupGamePlayer(void)2929 void SetupGamePlayer ( void )
2930 {
2931    int savetime;
2932    boolean done;
2933    boolean gameready;
2934 
2935    savetime=GetTicCount();
2936 
2937    done=false;
2938    gameready=false;
2939 
2940    while (done==false)
2941       {
2942 		// Setup individual player
2943       AbortCheck("SetupGamePlayer aborted\n");
2944 
2945       // send Player Description
2946 		if (GetTicCount() >= savetime)
2947          {
2948          savetime=GetTicCount()+SETUPTIME;
2949          if (gameready==false)
2950             SendPlayerDescription();
2951          else
2952             SendGameAck();
2953          }
2954       switch (SetupCheckForPacket())
2955          {
2956          case scfp_done:
2957             done=true;
2958             break;
2959          case scfp_gameready:
2960             gameready=true;
2961             break;
2962          }
2963       }
2964    savetime=GetTicCount()+(VBLCOUNTER/2);
2965 
2966    while (GetTicCount()<savetime)
2967       {
2968       SetupCheckForPacket ();
2969       }
2970 }
2971 
2972 //****************************************************************************
2973 //
2974 // AllPlayersReady ()
2975 //
2976 //****************************************************************************
AllPlayersReady(void)2977 boolean AllPlayersReady ( void )
2978 {
2979    int i;
2980 
2981 	for (i=0;i<numplayers;i++)
2982       if ((PlayersReady[i]==false) && (PlayerStatus[i]==player_ingame))
2983          return false;
2984 
2985    return true;
2986 }
2987 
2988 //****************************************************************************
2989 //
2990 // GotAllPlayerDescriptions ()
2991 //
2992 //****************************************************************************
GotAllPlayerDescriptions(void)2993 boolean GotAllPlayerDescriptions ( void )
2994 {
2995    int i;
2996 
2997 	for (i=0;i<numplayers;i++)
2998       if ((GotPlayersDesc[i]==false) && (PlayerStatus[i]==player_ingame))
2999          return false;
3000 
3001    return true;
3002 }
3003 
3004 //****************************************************************************
3005 //
3006 // SetupGameMaster ()
3007 //
3008 //****************************************************************************
SetupGameMaster(void)3009 void SetupGameMaster ( void )
3010 {
3011    int savetime;
3012    boolean done;
3013 
3014    memset(GotPlayersDesc,false,sizeof(GotPlayersDesc));
3015 	GotPlayersDesc[consoleplayer]=true;
3016 
3017    memset(PlayersReady,false,sizeof(PlayersReady));
3018 	PlayersReady[consoleplayer]=true;
3019 
3020    savetime=GetTicCount();
3021 
3022    done=false;
3023 
3024    InitializeRNG ();
3025 
3026    while (done==false)
3027       {
3028 		// Setup individual player
3029 
3030       AbortCheck("SetupGameMaster aborted\n");
3031 
3032       // send Game Description
3033 		if (GetTicCount() >= savetime)
3034          {
3035          savetime=GetTicCount()+SETUPTIME;
3036 			if (GotAllPlayerDescriptions()==true)
3037             SendGameDescription();
3038          }
3039       if (AllPlayersReady ()==true)
3040          {
3041          SendGameStart();
3042          SendGameStart();
3043          done=true;
3044          }
3045       SetupCheckForPacket();
3046       }
3047    savetime=GetTicCount()+(VBLCOUNTER/2);
3048 
3049    while (GetTicCount()<savetime)
3050       {
3051       SetupCheckForPacket ();
3052       }
3053 }
3054 
3055 
3056 
3057 
3058 
3059 
3060 
3061 
3062 
3063 
3064 /*
3065 =============================================================================
3066 
3067    DEMO CODE
3068 
3069 =============================================================================
3070 */
3071 //****************************************************************************
3072 //
3073 // GetDemoFilename ()
3074 //
3075 //****************************************************************************
3076 
GetDemoFilename(int demonumber,char * filename)3077 void GetDemoFilename (int demonumber, char * filename)
3078 {
3079    strcpy(filename,"demo0_0.dmo\0");
3080 
3081    filename[4] = (char)('0' + (byte)demonumber);
3082    filename[6] = (char)('0' + (byte)gamestate.violence);
3083 }
3084 //****************************************************************************
3085 //
3086 // DemoExists ()
3087 //
3088 //****************************************************************************
3089 
DemoExists(int demonumber)3090 boolean DemoExists (int demonumber)
3091 {
3092    char demo[20];
3093 
3094    GetDemoFilename (demonumber, &demo[0]);
3095    if (access (demo, F_OK) == 0)
3096       return true;
3097    else
3098       return false;
3099 
3100 }
3101 
3102 //****************************************************************************
3103 //
3104 // SaveDemo ()
3105 //
3106 //****************************************************************************
3107 
SaveDemo(int demonumber)3108 void SaveDemo (int demonumber)
3109 {
3110    char demo[20];
3111 
3112    RecordDemoCmd ();
3113    GetDemoFilename (demonumber, &demo[0]);
3114    SaveFile (demo, demobuffer, (demoptr-demobuffer));
3115    FreeDemo();
3116 }
3117 
3118 //****************************************************************************
3119 //
3120 // LoadDemo ()
3121 //
3122 //****************************************************************************
3123 
LoadDemo(int demonumber)3124 void LoadDemo (int demonumber)
3125 {
3126    char demo[20];
3127    int size;
3128 
3129    GetDemoFilename (demonumber, demo);
3130    if (demobuffer!=NULL)
3131       FreeDemo();
3132    size = LoadFile (demo, (void **)&demobuffer);
3133    playstate = ex_demoplayback;
3134    demoptr = demobuffer;
3135    lastdemoptr = (demoptr+size);
3136    locplayerstate->player=0;
3137    InitializeWeapons(locplayerstate);
3138    ResetPlayerstate(locplayerstate);
3139    InitCharacter();
3140 }
3141 
3142 //****************************************************************************
3143 //
3144 // RecordDemo ()
3145 //
3146 //****************************************************************************
3147 
RecordDemo(void)3148 void RecordDemo ( void )
3149 {
3150    DemoHeaderType * DemoHeader;
3151    int level;
3152 
3153    if (demobuffer!=NULL)
3154       FreeDemo();
3155    godmode=0;
3156    demobuffer = SafeMalloc (DEMOBUFFSIZE);
3157    demoptr = demobuffer;
3158    lastdemoptr = demobuffer+DEMOBUFFSIZE;
3159 
3160    // Save off level number
3161 
3162    DemoHeader=(DemoHeaderType *)demoptr;
3163    demoptr+=sizeof(gamestate);
3164    memcpy(&(DemoHeader->demostate),&gamestate,sizeof(gamestate));
3165    demorecord = true;
3166    locplayerstate->player=0;
3167    InitializeWeapons(locplayerstate);
3168    ResetPlayerstate(locplayerstate);
3169    level=gamestate.mapon;
3170    InitCharacter();
3171    gamestate.mapon=level;
3172    SoftError(">>>>>>>>>>>>Start demo record\n");
3173 }
3174 
3175 //****************************************************************************
3176 //
3177 // SetupDemo ()
3178 //
3179 //****************************************************************************
3180 
SetupDemo(void)3181 void SetupDemo ( void )
3182 {
3183    DemoHeaderType * DemoHeader;
3184 
3185    demoplayback = true;
3186    godmode=0;
3187 
3188    DemoHeader=(DemoHeaderType *)demoptr;
3189    demoptr+=sizeof(gamestate);
3190 //   if (gamestate.violence!=DemoHeader->demostate.violence)
3191 //      Error ("This demo has a different difficulty level than your current settings\n");
3192    memcpy(&gamestate,&(DemoHeader->demostate),sizeof(gamestate));
3193    SoftError(">>>>>>>>>>>>Start demo playback\n");
3194 }
3195 
3196 //****************************************************************************
3197 //
3198 // FreeDemo ()
3199 //
3200 //****************************************************************************
3201 
FreeDemo(void)3202 void FreeDemo ( void )
3203 {
3204    demoplayback = false;
3205    demorecord = false;
3206    SafeFree (demobuffer);
3207    demobuffer=NULL;
3208 }
3209 
3210 //****************************************************************************
3211 //
3212 // CheckForDemoDone ()
3213 //
3214 //****************************************************************************
3215 
CheckForDemoDone(void)3216 void CheckForDemoDone ( void )
3217 {
3218 	if ((demoplayback==true) && (demoptr >= lastdemoptr))
3219 		{
3220       FreeDemo();
3221       playstate = ex_demodone;
3222 		}
3223 }
3224 
3225 //****************************************************************************
3226 //
3227 // CheckForDemoOverflowed ()
3228 //
3229 //****************************************************************************
3230 
CheckForDemoOverflowed(void)3231 void CheckForDemoOverflowed ( void )
3232 {
3233 	if (demoptr >= (lastdemoptr-sizeof(DemoType)))
3234       {
3235       playstate = ex_completed;     // demo is done
3236       EndDemo();
3237       }
3238 }
3239 
3240 //****************************************************************************
3241 //
3242 // RecordDemoCmd ()
3243 //
3244 //****************************************************************************
3245 
RecordDemoCmd(void)3246 void RecordDemoCmd (void)
3247 {
3248    DemoType * dtime;
3249 
3250    SoftError("Demo command recorded at %ld\n",controlupdatetime);
3251    dtime=(DemoType *)demoptr;
3252    dtime->time = controlupdatetime;
3253    dtime->momx = (controlbuf[0]>>1);
3254    dtime->momy = (controlbuf[1]>>1);
3255    dtime->dangle = controlbuf[2]>>11;
3256    dtime->buttons = buttonbits;
3257 
3258    demoptr+=sizeof(DemoType);
3259 
3260    CheckForDemoOverflowed();
3261 }
3262 
3263 //****************************************************************************
3264 //
3265 // AddDemoCmd ()
3266 //
3267 //****************************************************************************
3268 
AddDemoCmd(void)3269 void AddDemoCmd (void)
3270 {
3271    DemoType * dtime;
3272 
3273    //
3274    // get info from demo buffer
3275    //
3276 
3277    SoftError("Demo command played at %ld\n",controlupdatetime);
3278    if (demoplayback==true)
3279       {
3280       dtime=(DemoType *)demoptr;
3281       controlbuf[0]=dtime->momx<<1;
3282       controlbuf[1]=dtime->momy<<1;
3283       controlbuf[2]=dtime->dangle<<11;
3284       buttonbits   =dtime->buttons;
3285       demoptr+=sizeof(DemoType);
3286 		}
3287 }
3288 
3289 //****************************************************************************
3290 //
3291 // GetNextDemoTime ()
3292 //
3293 //****************************************************************************
3294 
GetNextDemoTime(void)3295 int GetNextDemoTime (void)
3296 {
3297    DemoType * dtime;
3298 
3299    CheckForDemoDone();
3300    dtime=(DemoType *)demoptr;
3301    if (demoplayback)
3302       return dtime->time;
3303    else
3304       return -1;
3305 }
3306 
3307 //****************************************************************************
3308 //
3309 // UpdateDemoPlayback ()
3310 //
3311 //****************************************************************************
3312 
UpdateDemoPlayback(int time)3313 void UpdateDemoPlayback (int time)
3314 {
3315    if (demoplayback)
3316       {
3317       if (GetNextDemoTime()==time)
3318          AddDemoCmd();
3319       }
3320 }
3321 
3322 
3323 
3324 
3325 
3326