1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 1997, 2005 - 3D Realms Entertainment
4 
5 This file is part of Shadow Warrior version 1.2
6 
7 Shadow Warrior is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 
16 See the GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21 
22 Original Source: 1997 - Frank Maddin and Jim Norwood
23 Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
24 */
25 //-------------------------------------------------------------------------
26 
27 // CTW NOTE
28 /*
29 Known remaining issues:
30 - Audio stuttering.
31 - CD Audio not looping properly (currently hard coded to restart about every 200 seconds.
32 - Hitting F5 to change resolution causes a crash (currently disabled).
33 - Multiplayer untested.
34 
35 Things required to make savegames work:
36 - Load makesym.wpj and build it.
37 - In a DOS prompt, run "makesym sw.map swdata.map swcode.map"
38 - Copy swcode.map to swcode.sym and swdata.map to swdata.sym
39 */
40 // CTW NOTE END
41 
42 #define MAIN
43 #define QUIET
44 #include "build.h"
45 #include "baselayer.h"
46 #include "cache1d.h"
47 #include "osd.h"
48 #ifdef RENDERTYPEWIN
49 # include "winlayer.h"
50 #endif
51 
52 #include "keys.h"
53 #include "names2.h"
54 #include "panel.h"
55 #include "game.h"
56 #include "tags.h"
57 #include "sector.h"
58 #include "sprite.h"
59 #include "weapon.h"
60 #include "player.h"
61 #include "lists.h"
62 #include "net.h"
63 #include "pal.h"
64 #include "fx_man.h"
65 
66 #include "mytypes.h"
67 //#include "config.h"
68 
69 #include "menus.h"
70 
71 #include "control.h"
72 #include "function.h"
73 #include "gamedefs.h"
74 #include "config.h"
75 
76 #include "demo.h"
77 #include "cache.h"
78 //#include "exports.h"
79 
80 #include "anim.h"
81 
82 #include "colormap.h"
83 #include "break.h"
84 #include "ninja.h"
85 #include "light.h"
86 #include "track.h"
87 #include "jsector.h"
88 #include "keyboard.h"
89 #include "text.h"
90 #include "music.h"
91 
92 #include "crc32.h"
93 
94 #include "startwin.h"
95 #include "version.h"
96 
97 #if DEBUG
98 #define BETA 0
99 #endif
100 
101 #define STAT_SCREEN_PIC 5114
102 #define TITLE_PIC 2324
103 #define THREED_REALMS_PIC 2325
104 #define TITLE_ROT_FLAGS (ROTATE_SPRITE_CORNER|ROTATE_SPRITE_SCREEN_CLIP|ROTATE_SPRITE_NON_MASK)
105 #define PAL_SIZE (256*3)
106 
107 char DemoName[15][16];
108 
109 // Stupid WallMart version!
110 //#define PLOCK_VERSION TRUE
111 
112 #if PLOCK_VERSION
113 BOOL Global_PLock = TRUE;
114 #else
115 BOOL Global_PLock = FALSE;
116 #endif
117 
118 int GameVersion = 13;   // 12 was original source release. For future releases increment by two.
119 char DemoText[3][64];
120 int DemoTextYstart = 0;
121 
122 BOOL DoubleInitAWE32 = FALSE;
123 int Follow_posx=0,Follow_posy=0;
124 
125 BOOL NoMeters = FALSE;
126 short IntroAnimCount = 0;
127 short PlayingLevel = -1;
128 BOOL GraphicsMode = FALSE;
129 char CacheLastLevel[32] = "";
130 BOOL CleanExit = FALSE;
131 extern char cachedebug;
132 BOOL DemoModeMenuInit = FALSE;
133 BOOL FinishAnim = 0;
134 BOOL CachePrintMode = FALSE;
135 BOOL ShortGameMode = FALSE;
136 BOOL ReloadPrompt = FALSE;
137 BOOL ReloadPromptMode = FALSE;
138 BOOL NewGame = TRUE;
139 BOOL InMenuLevel = FALSE;
140 BOOL LoadGameOutsideMoveLoop = FALSE;
141 BOOL LoadGameFromDemo = FALSE;
142 BOOL ArgCheat = FALSE;
143 extern BOOL NetBroadcastMode, NetModeOverride;
144 BOOL MultiPlayQuitFlag = FALSE;
145 //Miscellaneous variables
146 char MessageInputString[256];
147 char MessageOutputString[256];
148 BOOL MessageInputMode = FALSE;
149 BOOL ConInputMode = FALSE;
150 BOOL ConPanel = FALSE;
151 BOOL FinishedLevel = FALSE;
152 BOOL HelpInputMode = FALSE;
153 BOOL PanelUpdateMode = TRUE;
154 short HelpPage = 0;
155 short HelpPagePic[] = { 5115, 5116, 5117 };
156 BOOL InputMode = FALSE;
157 BOOL MessageInput = FALSE;
158 extern BOOL GamePaused;
159 short screenpeek = 0;
160 BOOL NoDemoStartup = FALSE;
161 BOOL FirstTimeIntoGame;
162 extern BYTE RedBookSong[40];
163 
164 BOOL BorderAdjust = TRUE;
165 BOOL LocationInfo = 0;
166 VOID drawoverheadmap(int cposx, int cposy, int czoom, short cang);
167 int DispFrameRate = FALSE;
168 int DispMono = TRUE;
169 int Fog = FALSE;
170 int FogColor;
171 int PreCaching = TRUE;
172 int GodMode = FALSE;
173 int BotMode = FALSE;
174 short Skill = 2;
175 short BetaVersion = 900;
176 short TotalKillable;
177 
178 AUTO_NET Auto;
179 BOOL AutoNet = FALSE;
180 BOOL HasAutoColor = FALSE;
181 BYTE AutoColor;
182 
183 const GAME_SET gs_defaults = {
184 32768, // mouse speed
185 128, // music vol
186 192, // fx vol
187 2, // border
188 0, // brightness
189 0, // border tile
190 FALSE, // mouse aiming
191 FALSE, // mouse look
192 FALSE, // mouse invert
193 TRUE, // bobbing
194 FALSE, // tilting
195 TRUE, // shadows
196 FALSE, // auto run
197 TRUE, // crosshair
198 TRUE, // auto aim
199 TRUE, // messages
200 TRUE, // fx on
201 TRUE, // Music on
202 TRUE, // talking
203 TRUE, // ambient
204 FALSE, // Flip Stereo
205 
206 // Network game settings
207 0, // GameType
208 0, // Level
209 0, // Monsters
210 FALSE, // HurtTeammate
211 TRUE, // SpawnMarkers Markers
212 FALSE, // TeamPlay
213 0, // Kill Limit
214 0, // Time Limit
215 0, // Color
216 0, // Parental Lock
217 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", // Password
218 TRUE, // nuke
219 TRUE, // voxels
220 FALSE, // stats
221 FALSE, // mouse aiming on
222 FALSE, // play cd
223 "track??.ogg", // ogg track name
224 8, // panel scale
225 };
226 GAME_SET gs;
227 
228 char PlaxBits = 0;
229 BOOL PlayerTrackingMode = FALSE;
230 BOOL PauseMode = FALSE;
231 BOOL PauseKeySet = FALSE;
232 BOOL SlowMode = FALSE;
233 BOOL FrameAdvanceTics = 3;
234 BOOL ScrollMode2D = FALSE;
235 
236 BOOL DebugSO = FALSE;
237 BOOL DebugPanel = FALSE;
238 BOOL DebugSector = FALSE;
239 BOOL DebugActor = FALSE;
240 BOOL DebugAnim = FALSE;
241 BOOL DebugOperate = FALSE;
242 BOOL DebugActorFreeze = FALSE;
243 VOID LoadingLevelScreen(char *level_name);
244 
245 BYTE FakeMultiNumPlayers;
246 
247 int totalsynctics;
248 int turn_scale = 256;
249 int move_scale = 256;
250 
251 short Level = 0;
252 BOOL ExitLevel = FALSE;
253 SHORT OrigCommPlayers=0;
254 extern BYTE CommPlayers;
255 extern BOOL CommEnabled;
256 extern int bufferjitter;
257 
258 BOOL CameraTestMode = FALSE;
259 
260 char ds[256];                           // debug string
261 
262 extern short NormalVisibility;
263 
264 extern int quotebot, quotebotgoal;     // Multiplayer typing buffer
265 char recbuf[80];                        // Used as a temp buffer to hold typing text
266 
267 extern unsigned char palette_data[256][3];             // Global palette array
268 
269 #define ACT_STATUE 0
270 
271 int score;
272 BOOL QuitFlag = FALSE;
273 BOOL InGame = FALSE;
274 
275 int CommandSetup = FALSE;
276 
277 char UserMapName[80]="", buffer[80], ch;
278 char LevelName[20];
279 
280 BYTE DebugPrintColor = 255;
281 
282 int krandcount;
283 
284 /// L O C A L   P R O T O T Y P E S /////////////////////////////////////////////////////////
285 void BOT_DeleteAllBots( void );
286 VOID BotPlayerInsert(PLAYERp pp);
287 VOID SybexScreen(VOID);
288 VOID DosScreen(VOID);
289 VOID MenuLevel(VOID);
290 VOID StatScreen(PLAYERp mpp);
291 VOID InitRunLevel(VOID);
292 VOID RunLevel(VOID);
293 static int osdcmd_restartvid(const osdfuncparm_t *parm);
294 static int osdcmd_vidmode(const osdfuncparm_t *parm);
295 /////////////////////////////////////////////////////////////////////////////////////////////
296 
297 static FILE *debug_fout = NULL;
298 
DebugWriteString(char * string)299 VOID DebugWriteString(char *string)
300     {
301 
302     #if BETA || !DEBUG
303     return;
304     #endif
305 
306     if (!debug_fout)
307         {
308         if ((debug_fout = fopen("dbg.foo", "ab+")) == NULL)
309             return;
310         }
311 
312     fprintf(debug_fout, "%s\n", string);
313 
314     //fclose(debug_fout);
315     //debug_fout = NULL;
316 
317     fflush(debug_fout);
318     }
319 
DebugWriteLoc(char * fname,int line)320 VOID DebugWriteLoc(char *fname, int line)
321     {
322 
323     #if BETA || !DEBUG
324     return;
325     #endif
326 
327     if (!debug_fout)
328         {
329         if ((debug_fout = fopen("dbg.foo", "ab+")) == NULL)
330             return;
331         }
332 
333     fprintf(debug_fout, "%s, %d\n", fname, line);
334 
335     //fclose(debug_fout);
336     //debug_fout = NULL;
337 
338     fflush(debug_fout);
339     }
340 
341 
342 extern BOOL DrawScreen;
343 #if RANDOM_DEBUG
344 FILE *fout_err;
345 BOOL RandomPrint;
krand1(char * file,unsigned line)346 int krand1(char *file, unsigned line)
347     {
348     ASSERT(!DrawScreen);
349     if (RandomPrint && !Prediction)
350         { extern ULONG MoveThingsCount;
351         sprintf(ds,"mtc %d, %s, line %d, %d",MoveThingsCount,file,line,randomseed);
352         DebugWriteString(ds);
353         }
354     randomseed = ((randomseed * 21 + 1) & 65535);
355     return (randomseed);
356     }
357 
krand2()358 int krand2()
359     {
360     ASSERT(!DrawScreen);
361     randomseed = ((randomseed * 21 + 1) & 65535);
362     return (randomseed);
363     }
364 
365 #else
krand1(void)366 int krand1(void)
367     {
368     ASSERT(!DrawScreen);
369     krandcount++;
370     randomseed = ((randomseed * 21 + 1) & 65535);
371     return (randomseed);
372     }
373 
374 #endif
375 
376 VOID *
CacheAlloc(void ** ptr,int size,unsigned char * lock_byte)377 CacheAlloc(void **ptr, int size, unsigned char *lock_byte)
378     {
379     if (*ptr == NULL)
380         {
381         *lock_byte = CACHE_LOCK_START;
382         allocache(ptr, size, lock_byte);
383         }
384     else
385         {
386         if (*lock_byte < CACHE_LOCK_START)
387             *lock_byte = CACHE_LOCK_START;
388         else
389             (*lock_byte)++;
390        }
391 
392     return(*ptr);
393     }
394 
395 VOID
CacheFree(void ** ptr,unsigned char * lock_byte)396 CacheFree(void **ptr, unsigned char *lock_byte)
397     {
398     if (*ptr == NULL)
399         {
400         ASSERT(*lock_byte == NULL);
401         }
402     else
403         {
404         if (*lock_byte < CACHE_LOCK_START)
405             *lock_byte = CACHE_UNLOCK_START;
406        }
407     }
408 
409 /*
410 void HeapCheck(char *file, int line)
411 {
412     switch( _heapchk() )
413         {
414         case _HEAPOK:
415             //printf( "OK - heap is good\n" );
416             break;
417         case _HEAPEMPTY:
418             //printf( "OK - heap is empty\n" );
419             break;
420         case _HEAPBADBEGIN:
421             sprintf(ds, "ERROR - heap is damaged: %s, %d", file, line);
422             MONO_PRINT(ds);
423             DebugWriteString(ds);
424             setvmode(0x3);
425             printf( "%s\n", ds);
426             exit(0);
427             break;
428         case _HEAPBADNODE:
429             sprintf(ds, "ERROR - bad node in heap: %s, %d", file, line);
430             MONO_PRINT(ds);
431             DebugWriteString(ds);
432             setvmode(0x3);
433             printf( "%s\n", ds);
434             exit(0);
435             break;
436         }
437 }
438     */
439 
440 #if DEBUG
441 BOOL
ValidPtr(VOID * ptr)442 ValidPtr(VOID * ptr)
443     {
444     MEM_HDRp mhp;
445     BYTEp check;
446 
447     ASSERT(ptr != NULL);
448 
449     mhp = (MEM_HDRp) (((BYTEp) ptr) - sizeof(MEM_HDR));
450 
451     if (mhp->size == 0 || mhp->checksum == 0)
452         {
453     printf("ValidPtr(): Size or Checksum == 0!\n");
454         return (FALSE);
455         }
456 
457     check = (BYTEp) & mhp->size;
458 
459     if (mhp->checksum == check[0] + check[1] + check[2] + check[3])
460         return (TRUE);
461 
462     printf("ValidPtr(): Checksum bad!\n");
463     return (FALSE);
464     }
465 
466 VOID
PtrCheckSum(VOID * ptr,unsigned int * stored,unsigned int * actual)467 PtrCheckSum(VOID * ptr, unsigned int *stored, unsigned int *actual)
468     {
469     MEM_HDRp mhp;
470     BYTEp check;
471 
472     ASSERT(ptr != NULL);
473 
474     mhp = (MEM_HDRp) (((BYTEp) ptr) - sizeof(MEM_HDR));
475 
476     check = (BYTEp) & mhp->size;
477 
478     *stored = mhp->checksum;
479     *actual = check[0] + check[1] + check[2] + check[3];
480     }
481 
482 VOID *
AllocMem(int size)483 AllocMem(int size)
484     {
485     BYTEp bp;
486     MEM_HDRp mhp;
487     BYTEp check;
488 
489     ASSERT(size != 0);
490 
491     bp = (BYTEp) malloc(size + sizeof(MEM_HDR));
492 
493     // Used for debugging, we can remove this at ship time
494     if(bp == NULL)
495         {
496         TerminateGame();
497         printf("Memory could NOT be allocated in AllocMem: size = %d\n",size);
498         exit(0);
499         }
500 
501     ASSERT(bp != NULL);
502 
503     mhp = (MEM_HDRp) bp;
504 
505     mhp->size = size;
506     check = (BYTEp) & mhp->size;
507     mhp->checksum = check[0] + check[1] + check[2] + check[3];
508 
509     bp += sizeof(MEM_HDR);
510 
511     return (bp);
512     }
513 
514 VOID *
ReAllocMem(VOID * ptr,int size)515 ReAllocMem(VOID * ptr, int size)
516     {
517     BYTEp bp;
518     MEM_HDRp mhp;
519     BYTEp check;
520 
521     ASSERT(size != 0);
522 
523     ASSERT(ValidPtr(ptr));
524 
525     mhp = (MEM_HDRp) (((BYTEp) ptr) - sizeof(MEM_HDR));
526 
527     bp = (BYTEp) realloc(mhp, size + sizeof(MEM_HDR));
528 
529     ASSERT(bp != NULL);
530 
531     mhp = (MEM_HDRp) bp;
532 
533     mhp->size = size;
534     check = (BYTEp) & mhp->size;
535     mhp->checksum = check[0] + check[1] + check[2] + check[3];
536 
537     bp += sizeof(MEM_HDR);
538 
539     ASSERT(ValidPtr(bp));
540 
541     return (bp);
542     }
543 
544 
545 VOID *
CallocMem(int size,int num)546 CallocMem(int size, int num)
547     {
548     BYTEp bp;
549     MEM_HDRp mhp;
550     BYTEp check;
551     int num_bytes;
552 
553     ASSERT(size != 0 && num != 0);
554 
555     num_bytes = (size * num) + sizeof(MEM_HDR);
556     bp = (BYTEp) calloc(num_bytes, 1);
557 
558     // Used for debugging, we can remove this at ship time
559     if(bp == NULL)
560         {
561         TerminateGame();
562         printf("Memory could NOT be allocated in CallocMem: size = %d, num = %d\n",size,num);
563         exit(0);
564         }
565 
566     ASSERT(bp != NULL);
567 
568     mhp = (MEM_HDRp) bp;
569 
570     mhp->size = size;
571     check = (BYTEp) & mhp->size;
572     mhp->checksum = check[0] + check[1] + check[2] + check[3];
573 
574     bp += sizeof(MEM_HDR);
575 
576     return (bp);
577     }
578 
579 VOID
FreeMem(VOID * ptr)580 FreeMem(VOID * ptr)
581     {
582     MEM_HDRp mhp;
583     BYTEp check;
584 
585     ASSERT(ptr != NULL);
586 
587     ASSERT(ValidPtr(ptr));
588 
589     mhp = (MEM_HDRp) (((BYTEp) ptr) - sizeof(MEM_HDR));
590     check = (BYTEp)&mhp->size;
591 
592     memset(mhp, 0xCC, mhp->size + sizeof(MEM_HDR));
593 
594     free(mhp);
595     }
596 
597 #else
598 BOOL
ValidPtr(VOID * ptr)599 ValidPtr(VOID * ptr)
600     {
601     return (TRUE);
602     }
603 
604 VOID *
AllocMem(int size)605 AllocMem(int size)
606     {
607     return (malloc(size));
608     }
609 
610 VOID *
CallocMem(int size,int num)611 CallocMem(int size, int num)
612     {
613     return (calloc(size, num));
614     }
615 
616 VOID *
ReAllocMem(VOID * ptr,int size)617 ReAllocMem(VOID * ptr, int size)
618     {
619     return (realloc(ptr, size));
620     }
621 
622 VOID
FreeMem(VOID * ptr)623 FreeMem(VOID * ptr)
624     {
625     free(ptr);
626     }
627 
628 #endif
629 
PointOnLine(int x,int y,int x1,int y1,int x2,int y2)630 int PointOnLine(int x, int y, int x1, int y1, int x2, int y2)
631     {
632     // the closer to 0 the closer to the line the point is
633     return( ((x2 - x1) * (y - y1)) - ((y2 - y1) * (x - x1)) );
634     }
635 
636 int
Distance(int x1,int y1,int x2,int y2)637 Distance(int x1, int y1, int x2, int y2)
638     {
639     int min;
640 
641     if ((x2 = x2 - x1) < 0)
642         x2 = -x2;
643 
644     if ((y2 = y2 - y1) < 0)
645         y2 = -y2;
646 
647     if (x2 > y2)
648         min = y2;
649     else
650         min = x2;
651 
652     return (x2 + y2 - DIV2(min));
653     }
654 
655 VOID
MapSetAll2D(BYTE fill)656 MapSetAll2D(BYTE fill)
657     {
658     int i;
659 
660     for (i = 0; i < (MAXWALLS >> 3); i++)
661         show2dwall[i] = fill;
662     for (i = 0; i < (MAXSPRITES >> 3); i++)
663         show2dsprite[i] = fill;
664 
665     //for (i = 0; i < (MAXSECTORS >> 3); i++)
666     for (i = 0; i < MAXSECTORS; i++)
667         {
668         if (sector[i].ceilingpicnum != 342 && sector[i].floorpicnum != 342)
669             show2dsector[i>>3] |= (1<<(i&7));
670         //show2dsector[i] = fill;
671         }
672     }
673 
674 VOID
MapSetup(VOID)675 MapSetup(VOID)
676     {
677     #define NO_AUTO_MAPPING FALSE
678 
679     #if NO_AUTO_MAPPING
680     MapSetAll2D(0xFF);
681     #else
682     automapping = TRUE;
683     #endif
684     }
685 
686 VOID
setup2dscreen(VOID)687 setup2dscreen(VOID)
688     {
689       // qsetmode640350();
690     }
691 
692 
693 
694 VOID
TerminateGame(VOID)695 TerminateGame(VOID)
696     {
697     int i,j;
698     int oldtotalclock;
699 
700     DemoTerm();
701 
702     ErrorCorrectionQuit();
703 
704     uninitmultiplayers();
705 
706     if (CleanExit)
707         {
708         SybexScreen();
709         //TenScreen();
710         }
711 
712     ////--->>>> sound stuff was there
713     //uninitkeys();
714     KB_Shutdown();
715 
716     uninitengine();
717     TermSetup();
718 
719     //Terminate3DSounds();                // Kill the sounds linked list
720     UnInitSound();
721 
722     uninittimer();
723 
724     if (CleanExit)
725         DosScreen();
726 
727     uninitgroupfile();
728     }
729 
730 VOID
LoadLevel(char * filename)731 LoadLevel(char *filename)
732     {
733     int pos;
734 
735     if (loadboard(filename, SW_SHAREWARE ? 1 : 0, &Player[0].posx, &Player[0].posy, &Player[0].posz, &Player[0].pang, &Player[0].cursectnum) == -1)
736         {
737         TerminateGame();
738 #ifdef RENDERTYPEWIN
739     {
740         char msg[256];
741         Bsnprintf(msg, 256, "Level not found: %s", filename);
742         wm_msgbox(NULL, msg);
743     }
744 #else
745         printf("Level Not Found: %s\n", filename);
746 #endif
747         exit(0);
748         }
749     }
750 
751 VOID
LoadImages(char * filename)752 LoadImages(char *filename)
753     {
754     short ndx;
755     FILE *fin;
756 
757     if (loadpics(filename, 32*1048576) == -1)
758         {
759         TerminateGame();
760 #ifdef RENDERTYPEWIN
761     {
762         wm_msgbox(NULL, "Art not found. Please check your GRP file.");
763     }
764 #else
765         printf("Art not found. Please check your GRP file.\n");
766 #endif
767         exit(-1);
768         }
769     }
770 
LoadDemoRun(void)771 void LoadDemoRun(void)
772     {
773     short i;
774     FILE *fin;
775 
776     fin = fopen("demos.run","r");
777     if (fin)
778         {
779         memset(DemoName,'\0',sizeof(DemoName));
780         for (i = 0; TRUE; i++)
781             {
782             if (fscanf(fin, "%s", DemoName[i]) == EOF)
783                 break;
784             }
785 
786         fclose(fin);
787         }
788 
789     memset(DemoText,'\0',sizeof(DemoText));
790     fin = fopen("demotxt.run","r");
791     if (fin)
792         {
793         fgets(ds, 6, fin);
794         sscanf(ds,"%d",&DemoTextYstart);
795         for (i = 0; TRUE; i++)
796             {
797             if (fgets(DemoText[i], SIZ(DemoText[0])-1, fin) == NULL)
798                 break;
799             }
800 
801         fclose(fin);
802         }
803     }
804 
DisplayDemoText(void)805 void DisplayDemoText(void)
806     {
807     short w,h;
808     short i;
809 
810     for (i = 0; i < 3; i++)
811         {
812         MNU_MeasureString(DemoText[i], &w, &h);
813         PutStringTimer(Player, TEXT_TEST_COL(w), DemoTextYstart+(i*12), DemoText[i], 999);
814         }
815     }
816 
817 
Set_GameMode(void)818 void Set_GameMode(void)
819     {
820     extern int ScreenMode, ScreenWidth, ScreenHeight, ScreenBPP;
821     int result;
822     char ch;
823 
824     //DSPRINTF(ds,"ScreenMode %d, ScreenWidth %d, ScreenHeight %d",ScreenMode, ScreenWidth, ScreenHeight);
825     //MONO_PRINT(ds);
826     result = COVERsetgamemode(ScreenMode, ScreenWidth, ScreenHeight, ScreenBPP);
827 
828     if (result < 0)
829         {
830         buildprintf("Failure setting video mode %dx%dx%d %s! Attempting safer mode...",
831                 ScreenWidth,ScreenHeight,ScreenBPP,ScreenMode?"fullscreen":"windowed");
832         ScreenMode = 0;
833         ScreenWidth = 640;
834         ScreenHeight = 480;
835         ScreenBPP = 8;
836 
837         result = COVERsetgamemode(ScreenMode, ScreenWidth, ScreenHeight, ScreenBPP);
838         if (result < 0)
839             {
840             uninitmultiplayers();
841                 //uninitkeys();
842             KB_Shutdown();
843             uninitengine();
844             TermSetup();
845             UnInitSound();
846             uninittimer();
847             DosScreen();
848             uninitgroupfile();
849             exit(0);
850             }
851         }
852     }
853 
MultiSharewareCheck(void)854 void MultiSharewareCheck(void)
855     {
856     if (!SW_SHAREWARE) return;
857     if (numplayers > 4)
858         {
859         wm_msgbox(NULL,"To play a Network game with more than 4 players you must purchase "
860             "the full version.  Read the Ordering Info screens for details.");
861         uninitmultiplayers();
862         //uninitkeys();
863         KB_Shutdown();
864         uninitengine();
865         TermSetup();
866         UnInitSound();
867         uninittimer();
868         uninitgroupfile();
869         exit(0);
870         }
871      }
872 
873 
874 // Some mem crap for Jim
875 // I reserve 1 meg of heap space for our use out side the cache
876 int TotalMemory = 0;
877 int ActualHeap = 0;
878 
InitAutoNet(VOID)879 VOID InitAutoNet(VOID)
880     {
881     if (!AutoNet)
882         return;
883 
884     gs.NetGameType      = Auto.Rules;
885     gs.NetLevel         = Auto.Level;
886     gs.NetMonsters      = Auto.Enemy;
887     gs.NetSpawnMarkers  = Auto.Markers;
888     gs.NetTeamPlay      = Auto.Team;
889     gs.NetHurtTeammate  = Auto.HurtTeam;
890     gs.NetKillLimit     = Auto.Kill;
891     gs.NetTimeLimit     = Auto.Time;
892     gs.NetColor         = Auto.Color;
893     gs.NetNuke          = Auto.Nuke;
894     }
895 
896 
AnimateCacheCursor(void)897 void AnimateCacheCursor(void)
898     {
899 #if 0
900     struct rccoord old_pos;
901     static short cursor_num = 0;
902     static char cache_cursor[] =  {'|','/','-','\\'};
903 
904     if (GraphicsMode)
905         return;
906 
907     cursor_num++;
908     if (cursor_num > 3)
909         cursor_num = 0;
910 
911     //old_pos = _gettextposition();
912     //_settextposition( old_pos.row, old_pos.col );
913     //_settextposition( 24,  25);
914     _settextposition( 25,  0);
915     sprintf(ds,"Loading sound and graphics %c", cache_cursor[cursor_num]);
916     _outtext(ds);
917     //_settextposition( old_pos.row, old_pos.col );
918 #endif
919     }
920 
COVERsetbrightness(int bright,unsigned char * pal)921 void COVERsetbrightness(int bright, unsigned char *pal)
922 {
923 setbrightness(bright, pal, 0);
924 }
925 
926 
927 static int netsuccess = 0;
928 
929 int nextvoxid = 0;  // JBF
930 static const char *deffile = "sw.def";
931 
932 VOID
InitGame(VOID)933 InitGame(VOID)
934     {
935     extern int MovesPerPacket;
936     //void *ReserveMem=NULL;
937     int i;
938 
939         DSPRINTF(ds,"InitGame...");
940     MONO_PRINT(ds);
941 
942 
943     if (initengine()) {
944        wm_msgbox("Build Engine Initialisation Error",
945                "There was a problem initialising the Build engine: %s", engineerrstr);
946        exit(1);
947     }
948 
949     //initgroupfile("sw.grp");  // JBF: moving this close to start of program to detect shareware
950     InitSetup();
951 
952     InitAutoNet();
953 
954     inittimer(120);
955 
956     CON_InitConsole();  // Init console command list
957 
958     ////DSPRINTF(ds,"%s, %d",__FILE__,__LINE__);   MONO_PRINT(ds);
959 
960     //InitFX();
961 
962     memcpy(palette_data,palette,768);
963     InitPalette();
964 
965     // sets numplayers, connecthead, connectpoint2, myconnectindex
966     if (netsuccess) {
967         buildputs("Waiting for players...\n");
968         while (initmultiplayerscycle()) {
969             handleevents();
970             if (quitevent) {
971                 return;
972             }
973         }
974     } else {
975         initsingleplayers();
976     }
977 
978     initsynccrc();
979 
980     // code to duplicate packets
981     if (numplayers > 4 && MovesPerPacket == 1)
982         {
983         MovesPerPacket = 2;
984         }
985 
986     MultiSharewareCheck();
987 
988     CommPlayers = numplayers;
989     OrigCommPlayers = CommPlayers;
990     if (numplayers > 1)
991         {
992         CommEnabled = TRUE;
993         if(!BotMode)
994             gNet.MultiGameType = MULTI_GAME_COMMBAT;
995         else
996             gNet.MultiGameType = MULTI_GAME_AI_BOTS;
997         NetBroadcastMode = (networkmode == MMULTI_MODE_P2P);
998         }
999 
1000     LoadDemoRun();
1001     // Save off total heap for later calculations
1002     //TotalMemory = Z_AvailHeap();
1003     //DSPRINTF(ds,"Available Heap before LoadImages =  %d", TotalMemory);
1004     //MONO_PRINT(ds);
1005     // Reserve 1.5 megs for normal program use
1006     // Generally, SW is consuming about a total of 11 megs including
1007     // all the cached in graphics, etc. per level, so even on a 16 meg
1008     // system, reserving 1.5 megs is fine.
1009     // Note that on a 16 meg machine, Ken was leaving us about
1010     // 24k for use outside the cache!  This was causing out of mem problems
1011     // when songs, etc., greater than the remaining heap were being loaded.
1012     // Even if you pre-cache songs, etc. to help, reserving some heap is
1013     // a very smart idea since the game uses malloc throughout execution.
1014     //ReserveMem = AllocMem(1L<<20);
1015     //if(ReserveMem == 0) MONO_PRINT("Could not allocate 1.5 meg reserve!");
1016 
1017     // LoadImages will now proceed to steal all the remaining heap space
1018     //_outtext("\n\n\n\n\n\n\n\n");
1019     //AnimateCacheCursor();
1020     buildputs("Loading sound and graphics...\n");
1021     LoadImages("tiles000.art");
1022 
1023     // Now free it up for later use
1024     /*
1025     if(ReserveMem)
1026         {
1027         // Recalc TotalMemory for later reference
1028         ActualHeap = Z_AvailHeap() + 1536000L;
1029         FreeMem(ReserveMem);
1030         }
1031     */
1032 
1033     Connect();
1034     SortBreakInfo();
1035     //parallaxyoffs = 40;
1036     parallaxyoffs = 0;
1037     parallaxtype = 1;
1038     pskyoff[0] = 0;
1039     pskybits = PlaxBits;
1040     // Default scale value for parallax skies
1041     parallaxyscale = 8192;
1042 
1043     memset(Track, 0, sizeof(Track));
1044 
1045     memset(Player, 0, sizeof(Player));
1046     for (i = 0; i < MAX_SW_PLAYERS; i++)
1047         INITLIST(&Player[i].PanelSpriteList);
1048 
1049     LoadKVXFromScript( "swvoxfil.txt" );  // Load voxels from script file
1050     LoadPLockFromScript( "swplock.txt" ); // Get Parental Lock setup info
1051     if (!SW_SHAREWARE)
1052     LoadCustomInfoFromScript( "swcustom.txt" ); // Load user customisation information
1053 
1054     if (!loaddefinitionsfile(deffile)) buildputs("Definitions file loaded.\n");
1055 
1056     DemoModeMenuInit = TRUE;
1057     // precache as much stuff as you can
1058     if (UserMapName[0] == '\0')
1059         {
1060         AnimateCacheCursor();
1061         LoadLevel("$dozer.map");
1062         AnimateCacheCursor();
1063         SetupPreCache();
1064         DoTheCache();
1065         }
1066     else
1067         {
1068         AnimateCacheCursor();
1069         LoadLevel(UserMapName);
1070         AnimateCacheCursor();
1071         SetupPreCache();
1072         DoTheCache();
1073         }
1074 
1075     Set_GameMode();
1076     GraphicsMode = TRUE;
1077     SetupAspectRatio();
1078 
1079     COVERsetbrightness(gs.Brightness,&palette_data[0][0]);
1080 
1081     InitFX();   // JBF: do it down here so we get a hold of the window handle
1082     InitMusic();
1083 
1084     }
1085 
1086 
1087 /*
1088 Directory of C:\DEV\SW\MIDI
1089 EXECUT11 MID
1090 HROSHMA6 MID
1091 HOSHIA02 MID
1092 INTRO131 MID
1093 KOTEC2   MID
1094 KOTOKI12 MID
1095 NIPPON34 MID
1096 NOKI41   MID
1097 SANAI    MID
1098 SIANRA23 MID
1099 TKYO2007 MID
1100 TYTAIK16 MID
1101 YOKOHA03 MID
1102 */
1103 
1104 char LevelSong[16];
1105 short SongLevelNum;
1106 //#ifndef SW_SHAREWARE
1107 LEVEL_INFO LevelInfo[MAX_LEVELS_REG+2] =
1108     {
1109     {"title.map",      "theme.mid", " ", " ", " "  },
1110     {"$bullet.map",    "e1l01.mid", "Seppuku Station", "0 : 55", "5 : 00"  },
1111     {"$dozer.map",     "e1l03.mid", "Zilla Construction", "4 : 59", "8 : 00"  },
1112     {"$shrine.map",    "e1l02.mid", "Master Leep's Temple", "3 : 16", "10 : 00"  },
1113     {"$woods.map",     "e1l04.mid", "Dark Woods of the Serpent", "7 : 06", "16 : 00"  },
1114     {"$whirl.map",     "yokoha03.mid", "Rising Son", "5 : 30", "10 : 00"   },
1115     {"$tank.map",      "nippon34.mid", "Killing Fields", "1 : 46", "4 : 00"   },
1116     {"$boat.map",      "execut11.mid", "Hara-Kiri Harbor", "1 : 56", "4 : 00"   },
1117     {"$garden.map",    "execut11.mid", "Zilla's Villa", "1 : 06", "2 : 00"   },
1118     {"$outpost.map",   "sanai.mid",    "Monastery", "1 : 23", "3 : 00"      },
1119     {"$hidtemp.map",   "kotec2.mid",   "Raider of the Lost Wang", "2 : 05", "4 : 10"     },
1120     {"$plax1.map",     "kotec2.mid",   "Sumo Sky Palace", "6 : 32", "12 : 00"     },
1121     {"$bath.map",      "yokoha03.mid", "Bath House", "10 : 00", "10 : 00"   },
1122     {"$airport.map",   "nippon34.mid", "Unfriendly Skies", "2 : 59", "6 : 00"   },
1123     {"$refiner.map",   "kotoki12.mid", "Crude Oil", "2 : 40", "5 : 00"   },
1124     {"$newmine.map",   "hoshia02.mid", "Coolie Mines", "2 : 48", "6 : 00"   },
1125     {"$subbase.map",   "hoshia02.mid", "Subpen 7", "2 : 02", "4 : 00"   },
1126     {"$rock.map",      "kotoki12.mid", "The Great Escape", "3 : 18", "6 : 00"   },
1127     {"$yamato.map",    "sanai.mid",    "Floating Fortress", "11 : 38", "20 : 00"      },
1128     {"$seabase.map",   "kotec2.mid",   "Water Torture", "5 : 07", "10 : 00"     },
1129     {"$volcano.map",   "kotec2.mid",   "Stone Rain", "9 : 15", "20 : 00"     },
1130     {"$shore.map",     "kotec2.mid",   "Shanghai Shipwreck", "3 : 58", "8 : 00"     },
1131     {"$auto.map",      "kotec2.mid",   "Auto Maul", "4 : 07", "8 : 00"     },
1132     {"tank.map",       "kotec2.mid",   "Heavy Metal (DM only)", "10 : 00", "10 : 00"     },
1133     {"$dmwoods.map",   "kotec2.mid",   "Ripper Valley (DM only)", "10 : 00", "10 : 00"     },
1134     {"$dmshrin.map",   "kotec2.mid",   "House of Wang (DM only)", "10 : 00", "10 : 00"     },
1135     {"$rush.map",      "kotec2.mid",   "Lo Wang Rally (DM only)", "10 : 00", "10 : 00"     },
1136     {"shotgun.map",    "kotec2.mid",   "Ruins of the Ronin (CTF)", "10 : 00", "10 : 00"     },
1137     {"$dmdrop.map",    "kotec2.mid",   "Killing Fields (CTF)", "10 : 00", "10 : 00"     },
1138     {NULL, NULL, NULL, NULL, NULL}
1139     };
1140 /*#else
1141 LEVEL_INFO LevelInfo[MAX_LEVELS+2] =  // Shareware
1142     {
1143     {"title.map",      "theme.mid", " ", " ", " "  },
1144     {"$bullet.map",    "e1l01.mid", "Seppuku Station", "0 : 55", "5 : 00"  },
1145     {"$dozer.map",     "e1l03.mid", "Zilla Construction", "4 : 59", "8 : 00"  },
1146     {"$shrine.map",    "e1l02.mid", "Master Leep's Temple", "3 : 16", "10 : 00"  },
1147     {"$woods.map",     "e1l04.mid", "Dark Woods of the Serpent", "7 : 06", "16 : 00"  },
1148     {NULL, NULL, NULL, NULL, NULL}
1149     };
1150 #endif*/
1151 
1152 char EpisodeNames[2][MAX_EPISODE_NAME_LEN+2] = {
1153     "^Enter the Wang",
1154     "^Code of Honor"
1155 };
1156 char EpisodeSubtitles[2][MAX_EPISODE_SUBTITLE_LEN+1] = {
1157     "Four levels (Shareware Version)",
1158     "Eighteen levels (Full Version Only)"
1159 };
1160 char SkillNames[4][MAX_SKILL_NAME_LEN+2] = {
1161     "^Tiny grasshopper",
1162     "^I Have No Fear",
1163     "^Who Wants Wang",
1164     "^No Pain, No Gain"
1165 };
1166 
InitNewGame(VOID)1167 VOID InitNewGame(VOID)
1168     {
1169     int i, ready_bak;
1170     int ver_bak;
1171 
1172         //waitforeverybody();           // since ready flag resets after this point, need to carefully sync
1173 
1174     for (i = 0; i < MAX_SW_PLAYERS; i++)
1175         {
1176         // don't jack with the playerreadyflag
1177         ready_bak = Player[i].playerreadyflag;
1178         ver_bak = Player[i].PlayerVersion;
1179         memset(&Player[i], 0, sizeof(Player[i]));
1180         Player[i].playerreadyflag = ready_bak;
1181         Player[i].PlayerVersion = ver_bak;
1182         INITLIST(&Player[i].PanelSpriteList);
1183         }
1184 
1185     memset(puser, 0, sizeof(puser));
1186     }
1187 
FindLevelInfo(char * map_name,short * level)1188 void FindLevelInfo(char *map_name, short *level)
1189     {
1190     char *ptr;
1191     char buff[16];
1192     short i,j;
1193 
1194     for (j = 1; j <= MAX_LEVELS; j++)
1195         {
1196         if (LevelInfo[j].LevelName)
1197             {
1198             if (Bstrcasecmp(map_name, LevelInfo[j].LevelName) == 0)
1199                 {
1200                 *level = j;
1201                 return;
1202                 }
1203             }
1204         }
1205 
1206     *level = 0;
1207     return;
1208     }
1209 
1210 int ChopTics;
InitLevelGlobals(VOID)1211 VOID InitLevelGlobals(VOID)
1212     {
1213     extern char PlayerGravity;
1214     extern short wait_active_check_offset;
1215     //extern short Zombies;
1216     extern int PlaxCeilGlobZadjust, PlaxFloorGlobZadjust;
1217     extern BOOL left_foot;
1218     extern BOOL serpwasseen;
1219     extern BOOL sumowasseen;
1220     extern BOOL zillawasseen;
1221     extern short BossSpriteNum[3];
1222 
1223     // A few IMPORTANT GLOBAL RESETS
1224     // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1
1225     MapSetup();
1226     //Zombies = 0;
1227     ChopTics = 0;
1228     dimensionmode = 3;
1229     zoom = 768;
1230     PlayerGravity = 24;
1231     wait_active_check_offset = 0;
1232     PlaxCeilGlobZadjust = PlaxFloorGlobZadjust = Z(500);
1233     pskyoff[0] = 0;
1234     pskybits = PlaxBits;
1235     FinishedLevel = FALSE;
1236     AnimCnt = 0;
1237     left_foot = FALSE;
1238     screenpeek = myconnectindex;
1239 
1240     gNet.TimeLimitClock = gNet.TimeLimit;
1241 
1242     serpwasseen = FALSE;
1243     sumowasseen = FALSE;
1244     zillawasseen = FALSE;
1245     memset(BossSpriteNum,-1,sizeof(BossSpriteNum));
1246     }
1247 
InitLevelGlobals2(VOID)1248 VOID InitLevelGlobals2(VOID)
1249     {
1250     extern short Bunny_Count;
1251     // GLOBAL RESETS NOT DONE for LOAD GAME
1252     // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1253     InitTimingVars();
1254     TotalKillable = 0;
1255     Bunny_Count = 0;
1256     }
1257 
1258 VOID
InitLevel(VOID)1259 InitLevel(VOID)
1260     {
1261     static int DemoNumber = 0;
1262 
1263     MONO_PRINT("InitLevel");
1264     Terminate3DSounds();
1265 
1266     // A few IMPORTANT GLOBAL RESETS
1267     InitLevelGlobals();
1268     MONO_PRINT("InitLevelGlobals");
1269     if (!DemoMode)
1270         StopSong();
1271 
1272     if (LoadGameOutsideMoveLoop)
1273         {
1274           MONO_PRINT("Returning from InitLevel");
1275           return;
1276         }
1277 
1278     InitLevelGlobals2();
1279     MONO_PRINT("InitLevelGlobals2");
1280     if (DemoMode)
1281         {
1282         Level = 0;
1283         NewGame = TRUE;
1284         DemoInitOnce = FALSE;
1285         strcpy(DemoFileName, DemoName[DemoNumber]);
1286         DemoNumber++;
1287         if (!DemoName[DemoNumber][0])
1288             DemoNumber = 0;
1289 
1290         // read header and such
1291         DemoPlaySetup();
1292 
1293         strcpy(LevelName, DemoLevelName);
1294 
1295         FindLevelInfo(LevelName, &Level);
1296         if (Level > 0)
1297             {
1298             strcpy(LevelSong, LevelInfo[Level].SongName);
1299             strcpy(LevelName, LevelInfo[Level].LevelName);
1300             UserMapName[0] = '\0';
1301             }
1302         else
1303             {
1304             strcpy(UserMapName, DemoLevelName);
1305             Level = 0;
1306             }
1307 
1308         }
1309     else
1310         {
1311         if (Level < 0)
1312             Level = 0;
1313 
1314         if (Level > MAX_LEVELS)
1315             Level = 1;
1316 
1317         // extra code in case something is resetting these values
1318         if (NewGame)
1319             {
1320             //Level = 1;
1321             //DemoPlaying = FALSE;
1322             DemoMode = FALSE;
1323             //DemoRecording = FALSE;
1324             //DemoEdit = FALSE;
1325             }
1326 
1327         if (UserMapName[0])
1328             {
1329             strcpy(LevelName, UserMapName);
1330 
1331             Level = 0;
1332             FindLevelInfo(UserMapName, &Level);
1333 
1334             if (Level > 0)
1335                 {
1336                 // user map is part of game - treat it as such
1337                 strcpy(LevelSong, LevelInfo[Level].SongName);
1338                 strcpy(LevelName, LevelInfo[Level].LevelName);
1339                 UserMapName[0] = '\0';
1340                 }
1341             }
1342         else
1343             {
1344             strcpy(LevelName, LevelInfo[Level].LevelName);
1345             strcpy(LevelSong, LevelInfo[Level].SongName);
1346             }
1347         }
1348 
1349     PlayingLevel = Level;
1350 
1351     if (NewGame)
1352         InitNewGame();
1353 
1354     LoadingLevelScreen(LevelName);
1355     MONO_PRINT("LoadintLevelScreen");
1356     if (!DemoMode && !DemoInitOnce)
1357         DemoPlaySetup();
1358 
1359     LoadLevel(LevelName);
1360 
1361     if (!DemoMode)
1362         {
1363         char windowtitle[256];
1364 
1365         if (UserMapName[0])
1366             Bsnprintf(windowtitle, sizeof(windowtitle), "User map: %s - %s", UserMapName, gameeditionname);
1367         else
1368             Bsnprintf(windowtitle, sizeof(windowtitle), "%s - %s", LevelInfo[Level].Description, gameeditionname);
1369 
1370         windowtitle[sizeof(windowtitle)-1] = 0;
1371         wm_setwindowtitle(windowtitle);
1372         }
1373 
1374     if (Bstrcasecmp(CacheLastLevel, LevelName) != 0)
1375         // clears gotpic and does some bit setting
1376         SetupPreCache();
1377     else
1378         memset(gotpic,0,sizeof(gotpic));
1379 
1380     if (sector[0].extra != -1)
1381         {
1382         NormalVisibility = visibility = sector[0].extra;
1383         sector[0].extra = 0;
1384         }
1385     else
1386         NormalVisibility = visibility;
1387 
1388     //
1389     // Do Player stuff first
1390     //
1391 
1392     InitAllPlayers();
1393 
1394     #if DEBUG
1395     // fake Multi-player game setup
1396     if (FakeMultiNumPlayers && !BotMode)
1397         {
1398         BYTE i;
1399 
1400         // insert all needed players except the first one - its already tere
1401         for (i = 0; i < FakeMultiNumPlayers - 1; i++)
1402             {
1403             ManualPlayerInsert(Player);
1404             // reset control back to 1st player
1405             myconnectindex = 0;
1406             screenpeek = 0;
1407             }
1408         }
1409     #endif
1410 
1411     // Put in the BOTS if called for
1412     if (FakeMultiNumPlayers && BotMode)
1413         {
1414         BYTE i;
1415 
1416         // insert all needed players except the first one - its already tere
1417         for (i = 0; i < FakeMultiNumPlayers; i++)
1418             {
1419             BotPlayerInsert(Player);
1420             // reset control back to 1st player
1421             myconnectindex = 0;
1422             screenpeek = 0;
1423             }
1424         }
1425 
1426     QueueReset();
1427     PreMapCombineFloors();
1428     InitMultiPlayerInfo();
1429     InitAllPlayerSprites();
1430 
1431     //
1432     // Do setup for sprite, track, panel, sector, etc
1433     //
1434 
1435     // Set levels up
1436     InitTimingVars();
1437 
1438     SpriteSetup();
1439     SpriteSetupPost(); // post processing - already gone once through the loop
1440     InitLighting();
1441 
1442     TrackSetup();
1443 
1444     PlayerPanelSetup();
1445     MapSetup();
1446     SectorSetup();
1447     JS_InitMirrors();
1448     JS_InitLockouts();   // Setup the lockout linked lists
1449     JS_ToggleLockouts(); // Init lockouts on/off
1450 
1451     PlaceSectorObjectsOnTracks();
1452     PlaceActorsOnTracks();
1453     PostSetupSectorObject();
1454     SetupMirrorTiles();
1455     initlava();
1456 
1457     SongLevelNum = Level;
1458 
1459     if (DemoMode)
1460         {
1461         DisplayDemoText();
1462         }
1463 
1464 
1465     if (ArgCheat)
1466         {
1467         BOOL bak = gs.Messages;
1468         gs.Messages = FALSE;
1469         EveryCheatToggle(&Player[0],NULL);
1470         gs.Messages = bak;
1471         GodMode = TRUE;
1472         }
1473 
1474     // reset NewGame
1475     NewGame = FALSE;
1476 
1477     DSPRINTF(ds,"End of InitLevel...");
1478     MONO_PRINT(ds);
1479 
1480     #if 0
1481     #if DEBUG
1482     if (!cansee(43594, -92986, 0x3fffffff, 290,
1483         43180, -91707, 0x3fffffff, 290))
1484         {
1485         DSPRINTF(ds,"cansee failed");
1486         MONO_PRINT(ds);
1487         }
1488     #endif
1489     #endif
1490 
1491     }
1492 
1493 
1494 VOID
TerminateLevel(VOID)1495 TerminateLevel(VOID)
1496     {
1497     VOID pClearSpriteList(PLAYERp pp);
1498     int i, nexti, stat, pnum, ndx;
1499     SECT_USERp *sectu;
1500 
1501 //HEAP_CHECK();
1502 
1503     DemoTerm();
1504 
1505     // Free any track points
1506     for (ndx = 0; ndx < MAX_TRACKS; ndx++)
1507         {
1508         if (Track[ndx].TrackPoint)
1509             {
1510             FreeMem(Track[ndx].TrackPoint);
1511             // !JIM! I added null assigner
1512             Track[ndx].TrackPoint = NULL;
1513             }
1514         }
1515 
1516     // Clear the tracks
1517     memset(Track, 0, sizeof(Track));
1518 
1519     StopSound();
1520     Terminate3DSounds();        // Kill the 3d sounds linked list
1521     //ClearSoundLocks();
1522 
1523     // Clear all anims and any memory associated with them
1524     // Clear before killing sprites - save a little time
1525     //AnimClear();
1526 
1527     for (stat = STAT_PLAYER0; stat < STAT_PLAYER0 + CommPlayers; stat++)
1528         {
1529 
1530         pnum = stat - STAT_PLAYER0;
1531 
1532         TRAVERSE_SPRITE_STAT(headspritestat[stat], i, nexti)
1533             {
1534             if (User[i])
1535                 memcpy(&puser[pnum], User[i], sizeof(USER));
1536             }
1537         }
1538 
1539     // Kill User memory and delete sprites
1540     // for (stat = 0; stat < STAT_ALL; stat++)
1541     for (stat = 0; stat < MAXSTATUS; stat++)
1542         {
1543         TRAVERSE_SPRITE_STAT(headspritestat[stat], i, nexti)
1544             {
1545             KillSprite(i);
1546             }
1547         }
1548 
1549     // Free SectUser memory
1550     for (sectu = &SectUser[0];
1551         sectu < &SectUser[MAXSECTORS];
1552         sectu++)
1553         {
1554         if (*sectu)
1555             {
1556             ////DSPRINTF(ds,"Sect User Free %d",sectu-SectUser);
1557             //MONO_PRINT(ds);
1558             FreeMem(*sectu);
1559             *sectu = NULL;
1560             }
1561         }
1562 
1563     //memset(&User[0], 0, sizeof(User));
1564     memset(&SectUser[0], 0, sizeof(SectUser));
1565 
1566     TRAVERSE_CONNECT(pnum)
1567         {
1568         PLAYERp pp = Player + pnum;
1569 
1570         // Free panel sprites for players
1571         pClearSpriteList(pp);
1572 
1573         pp->DoPlayerAction = NULL;
1574 
1575         pp->SpriteP = NULL;
1576         pp->PlayerSprite = -1;
1577 
1578         pp->UnderSpriteP = NULL;
1579         pp->PlayerUnderSprite = -1;
1580 
1581         memset(pp->HasKey, 0, sizeof(pp->HasKey));
1582 
1583         //pp->WpnFlags = 0;
1584         pp->CurWpn = NULL;
1585 
1586         memset(pp->Wpn, 0, sizeof(pp->Wpn));
1587         memset(pp->InventorySprite, 0, sizeof(pp->InventorySprite));
1588         memset(pp->InventoryTics, 0, sizeof(pp->InventoryTics));
1589 
1590         pp->Killer = -1;
1591 
1592         INITLIST(&pp->PanelSpriteList);
1593         }
1594 
1595     JS_UnInitLockouts();
1596 
1597 //HEAP_CHECK();
1598     }
1599 
1600 VOID
NewLevel(VOID)1601 NewLevel(VOID)
1602     {
1603 
1604     DSPRINTF(ds,"NewLevel");
1605     MONO_PRINT(ds);
1606 
1607     if (DemoPlaying)
1608         {
1609         FX_SetVolume(0); // Shut the hell up while game is loading!
1610         InitLevel();
1611         InitRunLevel();
1612 
1613         DemoInitOnce = FALSE;
1614         if (DemoMode)
1615             {
1616             if (DemoModeMenuInit)
1617                 {
1618                 DemoModeMenuInit = FALSE;
1619                 ForceMenus = TRUE;
1620                 }
1621             }
1622 
1623         DemoPlayBack();
1624 
1625         if (DemoRecording && DemoEdit)
1626             {
1627             RunLevel();
1628             }
1629         }
1630     else
1631         {
1632         DSPRINTF(ds,"Calling FX_SetVolume");
1633         MONO_PRINT(ds);
1634         FX_SetVolume(0); // Shut the hell up while game is loading!
1635 
1636         DSPRINTF(ds,"Calling InitLevel");
1637         MONO_PRINT(ds);
1638         InitLevel();
1639 
1640         DSPRINTF(ds,"Calling RunLevel");
1641         MONO_PRINT(ds);
1642         RunLevel();
1643 
1644         if (!QuitFlag)
1645             {
1646             // for good measure do this
1647             ready2send = 0;
1648             waitforeverybody();
1649             }
1650 
1651         StatScreen(&Player[myconnectindex]);
1652         }
1653 
1654     if (LoadGameFromDemo)
1655         LoadGameFromDemo = FALSE;
1656     else
1657         TerminateLevel();
1658 
1659     InGame = FALSE;
1660 
1661     if (SW_SHAREWARE)
1662         {
1663         if (FinishAnim)
1664             MenuLevel();
1665         }
1666     else
1667         {
1668         if (FinishAnim == ANIM_ZILLA || FinishAnim == ANIM_SERP)
1669             MenuLevel();
1670         }
1671     FinishAnim = 0;
1672     }
1673 
1674 VOID
ResetKeys(VOID)1675 ResetKeys(VOID)
1676     {
1677     int i;
1678 
1679     for (i = 0; i < MAXKEYBOARDSCAN; i++)
1680         {
1681         KEY_PRESSED(i) = 0;
1682         }
1683     }
1684 
1685 BOOL
KeyPressed(VOID)1686 KeyPressed(VOID)
1687     {
1688     int i;
1689 
1690     for (i = 0; i < MAXKEYBOARDSCAN; i++)
1691         {
1692         if (KEY_PRESSED(i))
1693             return (TRUE);
1694         }
1695 
1696     return (FALSE);
1697     }
1698 
1699 BYTEp
KeyPressedRange(BYTEp kb,BYTEp ke)1700 KeyPressedRange(BYTEp kb, BYTEp ke)
1701     {
1702     BYTEp k;
1703 
1704     for (k = kb; k <= ke; k++)
1705         {
1706         if (*k)
1707             return (k);
1708         }
1709 
1710     return (NULL);
1711     }
1712 
1713 VOID
ResetKeyRange(BYTEp kb,BYTEp ke)1714 ResetKeyRange(BYTEp kb, BYTEp ke)
1715     {
1716     BYTEp k;
1717 
1718     for (k = kb; k <= ke; k++)
1719         {
1720         *k = 0;
1721         }
1722     }
1723 
1724 
1725 VOID
LogoLevel(VOID)1726 LogoLevel(VOID)
1727     {
1728     char called;
1729     int fin;
1730     unsigned char pal[PAL_SIZE];
1731     UserInput uinfo = { FALSE, FALSE, dir_None };
1732     int i;
1733 
1734 
1735     DSPRINTF(ds,"LogoLevel...");
1736     MONO_PRINT(ds);
1737 
1738     // start music at logo
1739     PlaySong(LevelInfo[0].SongName, RedBookSong[0], TRUE, TRUE);
1740 
1741     DSPRINTF(ds,"After music stuff...");
1742     MONO_PRINT(ds);
1743 
1744     // PreCache Anim
1745     LoadAnm(0);
1746 
1747     if ((fin = kopen4load("3drealms.pal", 0)) != -1)
1748         {
1749         kread(fin, pal, PAL_SIZE);
1750         kclose(fin);
1751         setbrightness(gs.Brightness, pal, 2);
1752         }
1753     DSPRINTF(ds,"Just read in 3drealms.pal...");
1754     MONO_PRINT(ds);
1755 
1756     //FadeOut(0, 0);
1757     ready2send = 0;
1758     totalclock = 0;
1759     ototalclock = 0;
1760 
1761     DSPRINTF(ds,"About to display 3drealms pic...");
1762     MONO_PRINT(ds);
1763 
1764     //FadeIn(0, 3);
1765 
1766     ResetKeys();
1767     while (TRUE)
1768         {
1769         clearallviews(0);
1770         rotatesprite(0, 0, RS_SCALE, 0, THREED_REALMS_PIC, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
1771         nextpage();
1772 
1773         handleevents();
1774         flushpackets();
1775 
1776         CONTROL_GetUserInput(&uinfo);
1777         CONTROL_ClearUserInput(&uinfo);
1778         if (quitevent) break;
1779 
1780         // taken from top of faketimerhandler
1781         // limits checks to max of 40 times a second
1782         if (totalclock >= ototalclock + synctics)
1783             {
1784             ototalclock += synctics;
1785             }
1786 
1787         if (totalclock > 5*120 || KeyPressed() || uinfo.button0 || uinfo.button1)
1788             {
1789             break;
1790             }
1791         }
1792 
1793     clearallviews(0);
1794     nextpage();
1795     setbrightness(gs.Brightness, &palette_data[0][0], 2);
1796 
1797     // put up a blank screen while loading
1798 
1799     DSPRINTF(ds,"End of LogoLevel...");
1800     MONO_PRINT(ds);
1801 
1802     }
1803 
1804 VOID
CreditsLevel(VOID)1805 CreditsLevel(VOID)
1806     {
1807     char called;
1808     int fin;
1809     int i;
1810     int curpic;
1811     int handle;
1812     ULONG timer = 0;
1813     int zero=0;
1814     short save;
1815     #define CREDITS1_PIC 5111
1816     #define CREDITS2_PIC 5118
1817 
1818     // put up a blank screen while loading
1819 
1820     // get rid of all PERM sprites!
1821     flushperms();
1822     save = gs.BorderNum;
1823     SetBorder(Player + myconnectindex,0);
1824     ClearStartMost();
1825     gs.BorderNum = save;
1826     clearallviews(0);
1827     nextpage();
1828 
1829     // Lo Wang feel like singing!
1830     handle = PlaySound(DIGI_JG95012,&zero,&zero,&zero,v3df_none);
1831 
1832     if (handle > 0)
1833         while(FX_SoundActive(handle))
1834             handleevents();
1835 
1836     // try 14 then 2 then quit
1837     if (!PlaySong(NULL, 14, FALSE, TRUE))
1838         {
1839         if (!PlaySong(NULL, 2, FALSE, TRUE))
1840             {
1841             handle = PlaySound(DIGI_NOLIKEMUSIC,&zero,&zero,&zero,v3df_none);
1842             if (handle > 0)
1843                 while(FX_SoundActive(handle))
1844                     handleevents();
1845             return;
1846             }
1847         }
1848 
1849     ready2send = 0;
1850     totalclock = 0;
1851     ototalclock = 0;
1852 
1853     ResetKeys();
1854     curpic = CREDITS1_PIC;
1855 
1856     while (TRUE)
1857         {
1858         handleevents();
1859         flushpackets();
1860 
1861         // taken from top of faketimerhandler
1862         // limits checks to max of 40 times a second
1863         if (totalclock >= ototalclock + synctics)
1864             {
1865             ototalclock += synctics;
1866             timer += synctics;
1867             }
1868 
1869         rotatesprite(0, 0, RS_SCALE, 0, curpic, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
1870 
1871         nextpage();
1872 
1873         if (timer > 8*120)
1874             {
1875             curpic = CREDITS2_PIC;
1876             }
1877 
1878         if (timer > 16*120)
1879             {
1880             timer = 0;
1881             curpic = CREDITS1_PIC;
1882             }
1883 
1884 
1885         if (!SongIsPlaying())
1886             break;
1887 
1888         if (KEY_PRESSED(KEYSC_ESC))
1889             break;
1890         }
1891 
1892     // put up a blank screen while loading
1893     clearallviews(0);
1894     nextpage();
1895     ResetKeys();
1896     StopSong();
1897     }
1898 
1899 
1900 VOID
SybexScreen(VOID)1901 SybexScreen(VOID)
1902     {
1903     UserInput uinfo;
1904 
1905     if (!SW_SHAREWARE) return;
1906 
1907     if (CommEnabled)
1908         return;
1909 
1910     rotatesprite(0, 0, RS_SCALE, 0, 5261, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
1911     nextpage();
1912 
1913     CONTROL_GetUserInput(&uinfo);
1914     CONTROL_ClearUserInput(&uinfo);
1915     ResetKeys();
1916     while (TRUE)
1917         {
1918         handleevents();
1919         CONTROL_GetUserInput(&uinfo);
1920         CONTROL_ClearUserInput(&uinfo);
1921         if (KeyPressed() || quitevent || uinfo.button0 || uinfo.button1)
1922             break;
1923         }
1924     }
1925 
1926 // CTW REMOVED
1927 /*
1928 VOID
1929 TenScreen(VOID)
1930     {
1931     char called;
1932     int fin;
1933     char backup_pal[256*3];
1934     char pal[PAL_SIZE];
1935     char tempbuf[256];
1936     char *palook_bak = palookup[0];
1937     int i;
1938     ULONG bak;
1939     int bakready2send;
1940 
1941     if (CommEnabled)
1942         return;
1943 
1944     bak = totalclock;
1945 
1946     flushperms();
1947     clearallviews(0);
1948     nextpage();
1949 
1950     for (i = 0; i < 256; i++)
1951         tempbuf[i] = i;
1952     palookup[0] = tempbuf;
1953 
1954     GetPaletteFromVESA(pal);
1955     memcpy(backup_pal, pal, PAL_SIZE);
1956 
1957     if ((fin = kopen4load("ten.pal", 0)) != -1)
1958         {
1959         kread(fin, pal, PAL_SIZE);
1960         kclose(fin);
1961         }
1962 
1963     // palette to black
1964     FadeOut(0, 0);
1965     bakready2send = ready2send;
1966     //totalclock = 0;
1967     //ototalclock = 0;
1968 
1969     flushperms();
1970     // draw it
1971     rotatesprite(0, 0, RS_SCALE, 0, TEN_PIC, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
1972     // bring to the front - still back palette
1973     nextpage();
1974     // set pal
1975     SetPaletteToVESA(pal);
1976     //FadeIn(0, 3);
1977     ResetKeys();
1978 
1979     while (!KeyPressed());
1980 
1981     palookup[0] = palook_bak;
1982 
1983     clearallviews(0);
1984     nextpage();
1985     SetPaletteToVESA(backup_pal);
1986 
1987     // put up a blank screen while loading
1988     clearallviews(0);
1989     nextpage();
1990 
1991     ready2send = bakready2send;
1992     totalclock = bak;
1993     }
1994 */
1995 // CTW REMOVED END
1996 
1997 VOID
TitleLevel(VOID)1998 TitleLevel(VOID)
1999     {
2000     char called;
2001     int fin;
2002     unsigned char backup_pal[256*3];
2003     unsigned char pal[PAL_SIZE];
2004     unsigned char tempbuf[256];
2005     unsigned char *palook_bak = palookup[0];
2006     int i;
2007 
2008     for (i = 0; i < 256; i++)
2009         tempbuf[i] = i;
2010     palookup[0] = tempbuf;
2011 
2012     //GetPaletteFromVESA(pal);
2013     //memcpy(backup_pal, pal, PAL_SIZE);
2014 
2015     clearallviews(0);
2016     nextpage();
2017 
2018 //    if ((fin = kopen4load("title.pal", 0)) != -1)
2019 //        {
2020 //        kread(fin, pal, PAL_SIZE);
2021 //        kclose(fin);
2022 //        SetPaletteToVESA(pal);
2023 //        }
2024 
2025 //    clearallviews(0);
2026 //    nextpage();
2027 
2028     //FadeOut(0, 0);
2029     ready2send = 0;
2030     totalclock = 0;
2031     ototalclock = 0;
2032 
2033     rotatesprite(0, 0, RS_SCALE, 0, TITLE_PIC, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
2034     nextpage();
2035     //FadeIn(0, 3);
2036 
2037     ResetKeys();
2038     while (TRUE)
2039         {
2040         handleevents();
2041         flushpackets();
2042         OSD_DispatchQueued();
2043 
2044         // taken from top of faketimerhandler
2045         // limits checks to max of 40 times a second
2046         if (totalclock >= ototalclock + synctics)
2047             {
2048             //void MNU_CheckForMenusAnyKey( void );
2049 
2050             ototalclock += synctics;
2051             //MNU_CheckForMenusAnyKey();
2052             }
2053 
2054         //if (UsingMenus)
2055         //    MNU_DrawMenu();
2056 
2057         //drawscreen as fast as you can
2058         rotatesprite(0, 0, RS_SCALE, 0, TITLE_PIC, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
2059 
2060         nextpage();
2061 
2062         if (totalclock > 5*120 || KeyPressed())
2063             {
2064             DemoMode = TRUE;
2065             DemoPlaying = TRUE;
2066             break;
2067             }
2068         }
2069 
2070     palookup[0] = palook_bak;
2071 
2072 //    clearallviews(0);
2073 //    nextpage();
2074     //SetPaletteToVESA(backup_pal);
2075 
2076     // put up a blank screen while loading
2077 //    clearallviews(0);
2078 //    nextpage();
2079     }
2080 
2081 
DrawMenuLevelScreen(VOID)2082 VOID DrawMenuLevelScreen(VOID)
2083     {
2084     flushperms();
2085     clearallviews(0);
2086     rotatesprite(0, 0, RS_SCALE, 0, TITLE_PIC, 20, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
2087     }
2088 
DrawStatScreen(VOID)2089 VOID DrawStatScreen(VOID)
2090     {
2091     flushperms();
2092     clearallviews(0);
2093     rotatesprite(0, 0, RS_SCALE, 0, STAT_SCREEN_PIC, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
2094     }
2095 
DrawLoadLevelScreen(VOID)2096 VOID DrawLoadLevelScreen(VOID)
2097     {
2098     flushperms();
2099     clearallviews(0);
2100     rotatesprite(0, 0, RS_SCALE, 0, TITLE_PIC, 20, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
2101     }
2102 
2103 short PlayerQuitMenuLevel = -1;
2104 
2105 VOID
IntroAnimLevel(VOID)2106 IntroAnimLevel(VOID)
2107     {
2108       DSPRINTF(ds,"IntroAnimLevel");
2109       MONO_PRINT(ds);
2110       playanm(0);
2111     }
2112 
2113 VOID
MenuLevel(VOID)2114 MenuLevel(VOID)
2115     {
2116     BOOL MNU_StartNetGame(void);
2117     char called;
2118     int fin;
2119     extern int totalclocklock;
2120     short w,h;
2121 
2122     DSPRINTF(ds,"MenuLevel...");
2123     MONO_PRINT(ds);
2124 
2125     wm_setwindowtitle(gameeditionname);
2126 
2127     if (gs.MusicOn)
2128         {
2129         PlaySong(LevelInfo[0].SongName, RedBookSong[0], TRUE, FALSE);
2130         }
2131 
2132     if (AutoNet)
2133         {
2134         DrawMenuLevelScreen();
2135 
2136         if (CommEnabled)
2137             {
2138             sprintf(ds,"Lo Wang is waiting for other players...");
2139             MNU_MeasureString(ds, &w, &h);
2140             MNU_DrawString(TEXT_TEST_COL(w), 170, ds, 1, 16);
2141 
2142             sprintf(ds,"They are afraid!");
2143             MNU_MeasureString(ds, &w, &h);
2144             MNU_DrawString(TEXT_TEST_COL(w), 180, ds, 1, 16);
2145             }
2146 
2147         nextpage();
2148 
2149         waitforeverybody();
2150                 FirstTimeIntoGame = TRUE;
2151         MNU_StartNetGame();
2152                 FirstTimeIntoGame = FALSE;
2153         waitforeverybody();
2154         ExitLevel = FALSE;
2155         FinishedLevel = FALSE;
2156         BorderAdjust = TRUE;
2157         UsingMenus = FALSE;
2158         InMenuLevel = FALSE;
2159         return;
2160         }
2161 
2162     // do demos only if not playing multi play
2163     if (!CommEnabled && CommPlayers <= 1 && !FinishAnim && !NoDemoStartup)
2164         {
2165         // demos exist - do demo instead
2166         if (DemoName[0][0] != '\0')
2167             {
2168             DemoMode = TRUE;
2169             DemoPlaying = TRUE;
2170             return;
2171             }
2172         }
2173 
2174     DemoMode = FALSE;
2175     DemoPlaying = FALSE;
2176 
2177     clearallviews(0);
2178     nextpage();
2179 
2180     //FadeOut(0, 0);
2181     ready2send = 0;
2182     totalclock = 0;
2183     ototalclock = 0;
2184     ExitLevel = FALSE;
2185     InMenuLevel = TRUE;
2186 
2187     DrawMenuLevelScreen();
2188 
2189     if (CommEnabled)
2190         {
2191         sprintf(ds,"Lo Wang is waiting for other players...");
2192         MNU_MeasureString(ds, &w, &h);
2193         MNU_DrawString(TEXT_TEST_COL(w), 170, ds, 1, 16);
2194 
2195         sprintf(ds,"They are afraid!");
2196         MNU_MeasureString(ds, &w, &h);
2197         MNU_DrawString(TEXT_TEST_COL(w), 180, ds, 1, 16);
2198         }
2199 
2200     nextpage();
2201     //FadeIn(0, 3);
2202 
2203     waitforeverybody();
2204 
2205     // don't allow BorderAdjusting in these menus
2206     BorderAdjust = FALSE;
2207 
2208     ResetKeys();
2209 
2210     if (SW_SHAREWARE)
2211         {
2212         // go to ordering menu only if shareware
2213         if (FinishAnim)
2214             {
2215             ForceMenus = TRUE;
2216             ControlPanelType = ct_ordermenu;
2217             FinishAnim = 0;
2218             }
2219         }
2220     else
2221         {
2222         FinishAnim = 0;
2223         }
2224 
2225     while (TRUE)
2226         {
2227         handleevents();
2228         OSD_DispatchQueued();
2229 
2230         if (quitevent)
2231             {
2232             if (CommPlayers >= 2)
2233                 MultiPlayQuitFlag = TRUE;
2234             else
2235                 QuitFlag = TRUE;
2236             }
2237 
2238         // taken from top of faketimerhandler
2239         // limits checks to max of 40 times a second
2240         if (totalclock >= ototalclock + synctics)
2241             {
2242             ototalclock += synctics;
2243             MNU_CheckForMenusAnyKey();
2244             if (CommEnabled)
2245                 getpackets();
2246             }
2247 
2248         if (CommEnabled)
2249             {
2250             if (MultiPlayQuitFlag)
2251                 {
2252                 short pnum;
2253                 BYTE pbuf[1];
2254                 QuitFlag = TRUE;
2255                 pbuf[0] = PACKET_TYPE_MENU_LEVEL_QUIT;
2256                 netbroadcastpacket(pbuf, 1);                      // TENSW
2257                 break;
2258                 }
2259 
2260             if (PlayerQuitMenuLevel >= 0)
2261                 {
2262                 MenuCommPlayerQuit(PlayerQuitMenuLevel);
2263                 PlayerQuitMenuLevel = -1;
2264                 }
2265             }
2266 
2267         if (ExitLevel)
2268             {
2269             // Quiting Level
2270             ExitLevel = FALSE;
2271             break;
2272             }
2273 
2274         if (QuitFlag)
2275             {
2276             // Quiting Game
2277             break;
2278             }
2279 
2280         // force the use of menus at all time
2281         if (!UsingMenus && !ConPanel)
2282             {
2283             ForceMenus = TRUE;
2284             MNU_CheckForMenusAnyKey();
2285             }
2286 
2287         // must lock the clock for drawing so animations will happen
2288         totalclocklock = totalclock;
2289 
2290         //drawscreen as fast as you can
2291         DrawMenuLevelScreen();
2292 
2293         if (UsingMenus)
2294             MNU_DrawMenu();
2295 
2296         nextpage();
2297         }
2298 
2299     BorderAdjust = TRUE;
2300     //LoadGameOutsideMoveLoop = FALSE;
2301     KEY_PRESSED(KEYSC_ESC) = FALSE;
2302     KB_ClearKeysDown();
2303     //ExitMenus();
2304     UsingMenus = FALSE;
2305     InMenuLevel = FALSE;
2306     clearallviews(0);
2307     nextpage();
2308     }
2309 
2310 VOID
SceneLevel(VOID)2311 SceneLevel(VOID)
2312     {
2313     BOOL dp_bak;
2314     BOOL dm_bak;
2315     FILE *fin;
2316     #define CINEMATIC_DEMO_FILE "$scene.dmo"
2317 
2318     // make sure it exists
2319     if ((fin = fopen(CINEMATIC_DEMO_FILE,"rb")) == NULL)
2320         return;
2321     else
2322         fclose(fin);
2323 
2324     strcpy(DemoFileName,CINEMATIC_DEMO_FILE);
2325 
2326     dp_bak = DemoPlaying;
2327     dm_bak = DemoMode;
2328 
2329     DemoMode = TRUE;
2330     DemoPlaying = TRUE;
2331     DemoOverride = TRUE;
2332     InitLevel();
2333     DemoOverride = FALSE;
2334 
2335     ScenePlayBack();
2336     TerminateLevel();
2337     DemoMode = dm_bak;
2338     DemoPlaying = dp_bak;
2339     }
2340 
2341 VOID
LoadingLevelScreen(char * level_name)2342 LoadingLevelScreen(char *level_name)
2343     {
2344     short w,h;
2345     extern BOOL DemoMode;
2346     extern char *MNU_LevelName[28];
2347     DrawLoadLevelScreen();
2348 
2349     if (DemoMode)
2350         sprintf(ds,"DEMO");
2351     else
2352         sprintf(ds,"ENTERING");
2353 
2354     MNU_MeasureString(ds, &w, &h);
2355     MNU_DrawString(TEXT_TEST_COL(w), 170, ds,1,16);
2356 
2357     if (UserMapName[0])
2358         sprintf(ds,"%s",UserMapName);
2359     else
2360         sprintf(ds,"%s",LevelInfo[Level].Description);
2361 
2362     MNU_MeasureString(ds, &w, &h);
2363     MNU_DrawString(TEXT_TEST_COL(w), 180, ds,1,16);
2364 
2365     nextpage();
2366     }
2367 
2368 VOID
gNextState(STATEp * State)2369 gNextState(STATEp *State)
2370     {
2371     // Transition to the next state
2372     *State = (*State)->NextState;
2373 
2374     if (TEST((*State)->Tics, SF_QUICK_CALL))
2375         {
2376         (*(*State)->Animator)(0);
2377         *State = (*State)->NextState;
2378         }
2379     }
2380 
2381 // Generic state control
2382 VOID
gStateControl(STATEp * State,int * tics)2383 gStateControl(STATEp *State, int *tics)
2384     {
2385     *tics += synctics;
2386 
2387     // Skip states if too much time has passed
2388     while (*tics >= (*State)->Tics)
2389         {
2390         // Set Tics
2391         *tics -= (*State)->Tics;
2392         gNextState(State);
2393         }
2394 
2395     // Call the correct animator
2396     if ((*State)->Animator)
2397         (*(*State)->Animator)(0);
2398     }
2399 
BonusPunchSound(short SpriteNum)2400 int BonusPunchSound(short SpriteNum)
2401     {
2402     PLAYERp pp = Player + myconnectindex;
2403     PlaySound(DIGI_PLAYERYELL3, &pp->posx, &pp->posy, &pp->posz, v3df_none);
2404     return(0);
2405     }
2406 
BonusKickSound(short SpriteNum)2407 int BonusKickSound(short SpriteNum)
2408     {
2409     PLAYERp pp = Player + myconnectindex;
2410     PlaySound(DIGI_PLAYERYELL2, &pp->posx, &pp->posy, &pp->posz, v3df_none);
2411     return(0);
2412     }
2413 
BonusGrabSound(short SpriteNum)2414 int BonusGrabSound(short SpriteNum)
2415     {
2416     PLAYERp pp = Player + myconnectindex;
2417     PlaySound(DIGI_BONUS_GRAB, &pp->posx, &pp->posy, &pp->posz, v3df_none);
2418     return(0);
2419     }
2420 
2421 VOID
BonusScreen(PLAYERp pp)2422 BonusScreen(PLAYERp pp)
2423     {
2424     int minutes,seconds,second_tics;
2425     extern BOOL FinishedLevel;
2426     extern int PlayClock;
2427     extern short LevelSecrets;
2428     extern short TotalKillable;
2429     short w,h;
2430     short pic,limit;
2431     int zero=0;
2432     int handle = 0;
2433     short LI_Num;
2434 
2435 
2436     #define BONUS_SCREEN_PIC 5120
2437     #define BONUS_ANIM 5121
2438     #define BONUS_ANIM_FRAMES (5159-5121)
2439 
2440     #define BREAK_LIGHT_RATE 18
2441 
2442     #define BONUS_PUNCH 5121
2443     #define BONUS_KICK 5136
2444     #define BONUS_GRAB 5151
2445     #define BONUS_REST 5121
2446 
2447     #define BONUS_TICS 8
2448     #define BONUS_GRAB_TICS 20
2449     #define BONUS_REST_TICS 50
2450 
2451     static STATE s_BonusPunch[] =
2452         {
2453         {BONUS_PUNCH + 0, BONUS_TICS, NULL, &s_BonusPunch[1]},
2454         {BONUS_PUNCH + 1, BONUS_TICS, NULL, &s_BonusPunch[2]},
2455         {BONUS_PUNCH + 2, BONUS_TICS, NULL, &s_BonusPunch[3]},
2456         {BONUS_PUNCH + 2, 0|SF_QUICK_CALL, BonusPunchSound, &s_BonusPunch[4]},
2457         {BONUS_PUNCH + 3, BONUS_TICS, NULL, &s_BonusPunch[5]},
2458         {BONUS_PUNCH + 4, BONUS_TICS, NULL, &s_BonusPunch[6]},
2459         {BONUS_PUNCH + 5, BONUS_TICS, NULL, &s_BonusPunch[7]},
2460         {BONUS_PUNCH + 6, BONUS_TICS, NULL, &s_BonusPunch[8]},
2461         {BONUS_PUNCH + 7, BONUS_TICS, NULL, &s_BonusPunch[9]},
2462         {BONUS_PUNCH + 8, BONUS_TICS, NULL, &s_BonusPunch[10]},
2463         {BONUS_PUNCH + 9, BONUS_TICS, NULL, &s_BonusPunch[11]},
2464         {BONUS_PUNCH + 10, BONUS_TICS, NULL, &s_BonusPunch[12]},
2465         {BONUS_PUNCH + 11, BONUS_TICS, NULL, &s_BonusPunch[13]},
2466         {BONUS_PUNCH + 12, BONUS_TICS, NULL, &s_BonusPunch[14]},
2467         {BONUS_PUNCH + 14, 90,        NULL, &s_BonusPunch[15]},
2468         {BONUS_PUNCH + 14, BONUS_TICS, NULL, &s_BonusPunch[15]},
2469         };
2470 
2471     static STATE s_BonusKick[] =
2472         {
2473         {BONUS_KICK + 0, BONUS_TICS, NULL, &s_BonusKick[1]},
2474         {BONUS_KICK + 1, BONUS_TICS, NULL, &s_BonusKick[2]},
2475         {BONUS_KICK + 2, BONUS_TICS, NULL, &s_BonusKick[3]},
2476         {BONUS_KICK + 2, 0|SF_QUICK_CALL, BonusKickSound, &s_BonusKick[4]},
2477         {BONUS_KICK + 3, BONUS_TICS, NULL, &s_BonusKick[5]},
2478         {BONUS_KICK + 4, BONUS_TICS, NULL, &s_BonusKick[6]},
2479         {BONUS_KICK + 5, BONUS_TICS, NULL, &s_BonusKick[7]},
2480         {BONUS_KICK + 6, BONUS_TICS, NULL, &s_BonusKick[8]},
2481         {BONUS_KICK + 7, BONUS_TICS, NULL, &s_BonusKick[9]},
2482         {BONUS_KICK + 8, BONUS_TICS, NULL, &s_BonusKick[10]},
2483         {BONUS_KICK + 9, BONUS_TICS, NULL, &s_BonusKick[11]},
2484         {BONUS_KICK + 10, BONUS_TICS, NULL, &s_BonusKick[12]},
2485         {BONUS_KICK + 11, BONUS_TICS, NULL, &s_BonusKick[13]},
2486         {BONUS_KICK + 12, BONUS_TICS, NULL, &s_BonusKick[14]},
2487         {BONUS_KICK + 14, 90,        NULL, &s_BonusKick[15]},
2488         {BONUS_KICK + 14, BONUS_TICS, NULL, &s_BonusKick[15]},
2489         };
2490 
2491     static STATE s_BonusGrab[] =
2492         {
2493         {BONUS_GRAB + 0, BONUS_GRAB_TICS, NULL, &s_BonusGrab[1]},
2494         {BONUS_GRAB + 1, BONUS_GRAB_TICS, NULL, &s_BonusGrab[2]},
2495         {BONUS_GRAB + 2, BONUS_GRAB_TICS, NULL, &s_BonusGrab[3]},
2496         {BONUS_GRAB + 2, 0|SF_QUICK_CALL, BonusGrabSound, &s_BonusGrab[4]},
2497         {BONUS_GRAB + 3, BONUS_GRAB_TICS, NULL, &s_BonusGrab[5]},
2498         {BONUS_GRAB + 4, BONUS_GRAB_TICS, NULL, &s_BonusGrab[6]},
2499         {BONUS_GRAB + 5, BONUS_GRAB_TICS, NULL, &s_BonusGrab[7]},
2500         {BONUS_GRAB + 6, BONUS_GRAB_TICS, NULL, &s_BonusGrab[8]},
2501         {BONUS_GRAB + 7, BONUS_GRAB_TICS, NULL, &s_BonusGrab[9]},
2502         {BONUS_GRAB + 8, BONUS_GRAB_TICS, NULL, &s_BonusGrab[10]},
2503         {BONUS_GRAB + 9, 90,             NULL, &s_BonusGrab[11]},
2504         {BONUS_GRAB + 9, BONUS_GRAB_TICS, NULL, &s_BonusGrab[11]},
2505         };
2506 
2507     #if 1 // Turned off the standing animate because he looks like a FAG!
2508     static STATE s_BonusRest[] =
2509         {
2510         {BONUS_REST + 0, BONUS_REST_TICS, NULL, &s_BonusRest[1]},
2511         {BONUS_REST + 1, BONUS_REST_TICS, NULL, &s_BonusRest[2]},
2512         {BONUS_REST + 2, BONUS_REST_TICS, NULL, &s_BonusRest[3]},
2513         {BONUS_REST + 1, BONUS_REST_TICS, NULL, &s_BonusRest[0]},
2514         };
2515     #else
2516     static STATE s_BonusRest[] =
2517         {
2518         {BONUS_REST + 0, BONUS_REST_TICS, NULL, &s_BonusRest[1]},
2519         {BONUS_REST + 0, BONUS_REST_TICS, NULL, &s_BonusRest[0]},
2520         };
2521     #endif
2522 
2523     static STATEp s_BonusAnim[] =
2524         {
2525         s_BonusPunch,
2526         s_BonusKick,
2527         s_BonusGrab
2528         };
2529 
2530     STATEp State = s_BonusRest;
2531 
2532     int Tics = 0;
2533     int line = 0;
2534     BOOL BonusDone;
2535     UserInput uinfo = { FALSE, FALSE, dir_None };
2536 
2537     if(Level < 0) Level = 0;
2538 
2539 	flushperms();
2540     clearallviews(0);
2541     nextpage();
2542 
2543     KB_ClearKeysDown();
2544 
2545     totalclock = ototalclock = 0;
2546     limit = synctics;
2547 
2548     if (gs.MusicOn)
2549         {
2550         PlaySong(voc[DIGI_ENDLEV].name, 3, TRUE, TRUE);
2551         }
2552 
2553     // special case code because I don't care any more!
2554     if (FinishAnim)
2555         {
2556         rotatesprite(0, 0, RS_SCALE, 0, 5120, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
2557         rotatesprite(158<<16, 86<<16, RS_SCALE, 0, State->Pic, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
2558         nextpage();
2559         FadeIn(0,0);
2560         }
2561 
2562     BonusDone = FALSE;
2563     while (!BonusDone)
2564         {
2565         handleevents();
2566         flushpackets();
2567 
2568         // taken from top of faketimerhandler
2569         if (totalclock < ototalclock + limit)
2570             {
2571             continue;
2572             }
2573         ototalclock += limit;
2574 
2575         CONTROL_GetUserInput(&uinfo);
2576         CONTROL_ClearUserInput(&uinfo);
2577         if (KEY_PRESSED(KEYSC_SPACE) || KEY_PRESSED(KEYSC_ENTER) || uinfo.button0 || uinfo.button1)
2578             {
2579             if (State >= s_BonusRest && State < &s_BonusRest[SIZ(s_BonusRest)])
2580                 {
2581                 State = s_BonusAnim[STD_RANDOM_RANGE(SIZ(s_BonusAnim))];
2582                 Tics = 0;
2583                 }
2584             }
2585 
2586         gStateControl(&State, &Tics);
2587 		clearallviews(0);
2588         rotatesprite(0, 0, RS_SCALE, 0, 5120, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
2589 
2590         if (UserMapName[0])
2591             {
2592             sprintf(ds,"%s",UserMapName);
2593             MNU_MeasureString(ds, &w, &h);
2594             MNU_DrawString(TEXT_TEST_COL(w), 20, ds,1,19);
2595             }
2596         else
2597             {
2598             if (PlayingLevel <= 1)
2599                 PlayingLevel = 1;
2600             sprintf(ds,"%s",LevelInfo[PlayingLevel].Description);
2601             MNU_MeasureString(ds, &w, &h);
2602             MNU_DrawString(TEXT_TEST_COL(w), 20, ds,1,19);
2603             }
2604 
2605         sprintf(ds,"Completed");
2606         MNU_MeasureString(ds, &w, &h);
2607         MNU_DrawString(TEXT_TEST_COL(w), 30, ds,1,19);
2608 
2609         rotatesprite(158<<16, 86<<16, RS_SCALE, 0, State->Pic, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
2610 
2611         #define BONUS_LINE(i) (50 + ((i)*20))
2612 
2613         line = 0;
2614         second_tics = (PlayClock/120);
2615         minutes = (second_tics/60);
2616         seconds = (second_tics%60);
2617         sprintf(ds,"Your Time:  %2d : %02d", minutes, seconds);
2618         MNU_MeasureString(ds, &w, &h);
2619         MNU_DrawString(60, BONUS_LINE(line), ds,1,16);
2620 
2621         if (!UserMapName[0])
2622             {
2623             line++;
2624             sprintf(ds,"3D Realms Best Time:  %s", LevelInfo[PlayingLevel].BestTime);
2625             MNU_MeasureString(ds, &w, &h);
2626             MNU_DrawString(40, BONUS_LINE(line), ds,1,16);
2627 
2628             line++;
2629             sprintf(ds,"Par Time:  %s", LevelInfo[PlayingLevel].ParTime);
2630             MNU_MeasureString(ds, &w, &h);
2631             MNU_DrawString(40, BONUS_LINE(line), ds,1,16);
2632             }
2633 
2634 
2635         // always read secrets and kills from the first player
2636         line++;
2637         sprintf(ds,"Secrets:  %d / %d", Player->SecretsFound, LevelSecrets);
2638         MNU_MeasureString(ds, &w, &h);
2639         MNU_DrawString(60, BONUS_LINE(line), ds,1,16);
2640 
2641         line++;
2642         sprintf(ds,"Kills:  %d / %d", Player->Kills, TotalKillable);
2643         MNU_MeasureString(ds, &w, &h);
2644         MNU_DrawString(60, BONUS_LINE(line), ds,1,16);
2645 
2646 
2647         sprintf(ds,"Press SPACE to continue");
2648         MNU_MeasureString(ds, &w, &h);
2649         MNU_DrawString(TEXT_TEST_COL(w), 185, ds,1,19);
2650 
2651         nextpage();
2652         ScreenCaptureKeys();
2653 
2654         if (State == State->NextState)
2655             BonusDone = TRUE;
2656         }
2657 
2658     StopSound();
2659     Terminate3DSounds();
2660     }
2661 
EndGameSequence(VOID)2662 VOID EndGameSequence(VOID)
2663     {
2664     BOOL anim_ok = TRUE;
2665     FadeOut(0, 5);
2666 
2667     if ((gs.ParentalLock || Global_PLock) && FinishAnim == ANIM_SUMO)
2668         anim_ok = FALSE;
2669 
2670     if (anim_ok)
2671         playanm(FinishAnim);
2672 
2673     BonusScreen(Player + myconnectindex);
2674 
2675     ExitLevel = FALSE;
2676     QuitFlag = FALSE;
2677     AutoNet = FALSE;
2678 
2679     if (FinishAnim == ANIM_ZILLA)
2680         CreditsLevel();
2681 
2682     ExitLevel = FALSE;
2683     QuitFlag = FALSE;
2684     AutoNet = FALSE;
2685 
2686     if (SW_SHAREWARE) {
2687         Level = 0;
2688     } else {
2689         if (Level == 4 || Level == 20)
2690             {
2691             //CDAudio_Stop();
2692             //CDAudio_Play(2,TRUE); // Play theme after game ends
2693             Level=0;
2694             }
2695         else
2696             Level++;
2697     }
2698     }
2699 
2700 VOID
StatScreen(PLAYERp mpp)2701 StatScreen(PLAYERp mpp)
2702     {
2703     int minutes,seconds,second_tics;
2704     extern BOOL FinishedLevel;
2705     extern int PlayClock;
2706     extern short LevelSecrets;
2707     extern short TotalKillable;
2708     short w,h;
2709     int zero=0;
2710     int handle=0;
2711 
2712     short rows,cols,i,j;
2713     PLAYERp pp = NULL;
2714     int x,y;
2715     short death_total[MAX_SW_PLAYERS_REG];
2716     short kills[MAX_SW_PLAYERS_REG];
2717     short pal;
2718 
2719     UserInput uinfo = { FALSE, FALSE, dir_None };
2720 
2721     #define STAT_START_X 20
2722     #define STAT_START_Y 85
2723     #define STAT_OFF_Y 9
2724     #define STAT_HEADER_Y 14
2725 
2726     #define SM_SIZ(num) ((num)*4)
2727 
2728     #define STAT_TABLE_X (STAT_START_X + SM_SIZ(15))
2729     #define STAT_TABLE_XOFF SM_SIZ(6)
2730 
2731     // No stats in bot games
2732     //if (BotMode) return;
2733 
2734     ResetPalette(mpp);
2735     COVER_SetReverb(0); // Reset reverb
2736     StopSound();
2737 
2738     if (FinishAnim)
2739         {
2740         EndGameSequence();
2741         return;
2742         }
2743 
2744     if (gNet.MultiGameType != MULTI_GAME_COMMBAT)
2745         {
2746         if (!FinishedLevel)
2747             return;
2748         BonusScreen(mpp);
2749         return;
2750         }
2751 
2752     flushperms();
2753     DrawStatScreen();
2754 
2755     memset(death_total,0,sizeof(death_total));
2756     memset(kills,0,sizeof(kills));
2757 
2758     sprintf(ds,"MULTIPLAYER TOTALS");
2759     MNU_MeasureString(ds, &w, &h);
2760     MNU_DrawString(TEXT_TEST_COL(w), 68, ds, 0, 0);
2761 
2762     sprintf(ds,"PRESS SPACE BAR TO CONTINUE");
2763     MNU_MeasureString(ds, &w, &h);
2764     MNU_DrawString(TEXT_TEST_COL(w), 189, ds, 0, 0);
2765 
2766     x = STAT_START_X;
2767     y = STAT_START_Y;
2768 
2769     sprintf(ds,"  NAME         1     2     3     4     5     6     7    8     KILLS");
2770     DisplayMiniBarSmString(mpp, x, y, 0, ds);
2771     rows = OrigCommPlayers;
2772     cols = OrigCommPlayers;
2773     mpp = Player + myconnectindex;
2774 
2775     y += STAT_HEADER_Y;
2776 
2777     for (i = 0; i < rows; i++)
2778         {
2779         x = STAT_START_X;
2780         pp = Player + i;
2781 
2782         sprintf(ds,"%d", i+1);
2783         DisplayMiniBarSmString(mpp, x, y, 0, ds);
2784 
2785         sprintf(ds,"  %-13s", pp->PlayerName);
2786         DisplayMiniBarSmString(mpp, x, y, User[pp->PlayerSprite]->spal, ds);
2787 
2788         x = STAT_TABLE_X;
2789         for (j = 0; j < cols; j++)
2790             {
2791             pal = 0;
2792             death_total[j] += pp->KilledPlayer[j];
2793 
2794             if (i == j)
2795                 {
2796                 // don't add kill for self or team player
2797                 pal = PALETTE_PLAYER0 + 4;
2798                 kills[i] -= pp->KilledPlayer[j];  // subtract self kills
2799                 }
2800             else
2801             if (gNet.TeamPlay)
2802                 {
2803                 if (User[pp->PlayerSprite]->spal == User[Player[j].PlayerSprite]->spal)
2804                     {
2805                     // don't add kill for self or team player
2806                     pal = PALETTE_PLAYER0 + 4;
2807                     kills[i] -= pp->KilledPlayer[j];  // subtract self kills
2808                     } else
2809                     kills[i] += pp->KilledPlayer[j];  // kills added here
2810                 }
2811             else
2812                 {
2813                 kills[i] += pp->KilledPlayer[j];  // kills added here
2814                 }
2815 
2816             sprintf(ds,"%d", pp->KilledPlayer[j]);
2817             DisplayMiniBarSmString(mpp, x, y, pal, ds);
2818             x += STAT_TABLE_XOFF;
2819             }
2820 
2821         y += STAT_OFF_Y;
2822         }
2823 
2824 
2825     // Deaths
2826 
2827     x = STAT_START_X;
2828     y += STAT_OFF_Y;
2829 
2830     sprintf(ds,"   DEATHS");
2831     DisplayMiniBarSmString(mpp, x, y, 0, ds);
2832     x = STAT_TABLE_X;
2833 
2834     for (j = 0; j < cols; j++)
2835         {
2836         sprintf(ds,"%d",death_total[j]);
2837         DisplayMiniBarSmString(mpp, x, y, 0, ds);
2838         x += STAT_TABLE_XOFF;
2839         }
2840 
2841     x = STAT_START_X;
2842     y += STAT_OFF_Y;
2843 
2844     // Kills
2845     x = STAT_TABLE_X + SM_SIZ(50);
2846     y = STAT_START_Y + STAT_HEADER_Y;
2847 
2848     for (i = 0; i < rows; i++)
2849         {
2850         pp = Player + i;
2851 
2852         sprintf(ds,"%d", kills[i]);//pp->Kills);
2853         DisplayMiniBarSmString(mpp, x, y, 0, ds);
2854 
2855         y += STAT_OFF_Y;
2856         }
2857 
2858     nextpage();
2859 
2860     KB_ClearKeysDown();
2861 
2862     if (gs.MusicOn)
2863         {
2864         PlaySong(voc[DIGI_ENDLEV].name, 3, TRUE, TRUE);
2865         }
2866 
2867     while (TRUE)
2868         {
2869         handleevents();
2870         flushpackets();
2871         if (quitevent) break;
2872 
2873         CONTROL_GetUserInput(&uinfo);
2874         CONTROL_ClearUserInput(&uinfo);
2875         if (KEY_PRESSED(KEYSC_SPACE) || KEY_PRESSED(KEYSC_ENTER) || uinfo.button0 || uinfo.button1)
2876             {
2877             break;
2878             }
2879 
2880         ScreenCaptureKeys();
2881         }
2882 
2883     StopSound();
2884     Terminate3DSounds();
2885     }
2886 
2887 VOID
GameIntro(VOID)2888 GameIntro(VOID)
2889     {
2890 
2891     DSPRINTF(ds,"GameIntro...");
2892     MONO_PRINT(ds);
2893 
2894     wm_setwindowtitle(gameeditionname);
2895 
2896     if (DemoPlaying)
2897         return;
2898 
2899     // this could probably be taken out and you could select skill level
2900     // from menu to start the game
2901     if (!CommEnabled && UserMapName[0])
2902         return;
2903 
2904     Level = 1;
2905 
2906 
2907 
2908 
2909     if (!AutoNet)
2910         {
2911         LogoLevel();
2912         //CreditsLevel();
2913         //SceneLevel();
2914         //TitleLevel();
2915         IntroAnimLevel();
2916         IntroAnimCount = 0;
2917         }
2918 
2919     MenuLevel();
2920     }
2921 
2922 VOID
Control(VOID)2923 Control(VOID)
2924     {
2925 
2926     InitGame();
2927 
2928         MONO_PRINT("InitGame done");
2929     MNU_InitMenus();
2930     InGame = TRUE;
2931     GameIntro();
2932     //NewGame = TRUE;
2933 
2934     while (!QuitFlag)
2935         {
2936         NewLevel();
2937         }
2938 
2939     CleanExit = TRUE;
2940     TerminateGame();
2941     }
2942 
2943 
2944 void
_Assert(char * expr,char * strFile,unsigned uLine)2945 _Assert(char *expr, char *strFile, unsigned uLine)
2946     {
2947     sprintf(ds, "Assertion failed: %s %s, line %u", expr, strFile, uLine);
2948     MONO_PRINT(ds);
2949     TerminateGame();
2950 #if 1 //def RENDERTYPEWIN
2951     wm_msgbox(NULL, "%s", ds);
2952 #else
2953     printf("Assertion failed: %s\n %s, line %u\n", expr, strFile, uLine);
2954 #endif
2955     exit(0);
2956     }
2957 
2958 
2959 void
_ErrMsg(char * strFile,unsigned uLine,char * format,...)2960 _ErrMsg(char *strFile, unsigned uLine, char *format, ...)
2961     {
2962     va_list arglist;
2963 
2964     //DSPRINTF(ds, "Error: %s, line %u", strFile, uLine);
2965     //MONO_PRINT(ds);
2966     TerminateGame();
2967 
2968 #if 1 //def RENDERTYPEWIN
2969     {
2970         char msg[256], *p;
2971         Bsnprintf(msg, sizeof(msg), "Error: %s, line %u\n", strFile, uLine);
2972         p = &msg[strlen(msg)];
2973         va_start( arglist, format );
2974         Bvsnprintf(msg, sizeof(msg) - (p-msg), format, arglist);
2975         va_end(arglist);
2976         wm_msgbox(NULL, "%s", msg);
2977     }
2978 #else
2979     printf("Error: %s, line %u\n", strFile, uLine);
2980 
2981     va_start( arglist, format );
2982     vprintf( format, arglist );
2983     va_end( arglist );
2984 #endif
2985 
2986     exit(0);
2987     }
2988 
2989 void
dsprintf(char * str,char * format,...)2990 dsprintf(char *str, char *format, ...)
2991     {
2992     va_list arglist;
2993 
2994     va_start( arglist, format );
2995     vsprintf( str, format, arglist );
2996     va_end( arglist );
2997     }
2998 
2999 void
dsprintf_null(char * str,char * format,...)3000 dsprintf_null(char *str, char *format, ...)
3001     {
3002     va_list arglist;
3003     }
3004 
MoveLoop(void)3005 void MoveLoop(void)
3006     {
3007     int pnum;
3008 
3009     getpackets();
3010 
3011     if (PredictionOn && CommEnabled)
3012         {
3013         while (predictmovefifoplc < Player[myconnectindex].movefifoend)
3014             {
3015             DoPrediction(ppp);
3016             }
3017         }
3018 
3019        //While you have new input packets to process...
3020     if (!CommEnabled)
3021         bufferjitter = 0;
3022 
3023     while (Player[myconnectindex].movefifoend - movefifoplc > bufferjitter)
3024         {
3025            //Make sure you have at least 1 packet from everyone else
3026          TRAVERSE_CONNECT(pnum)
3027             {
3028             if (movefifoplc == Player[pnum].movefifoend)
3029                 break;
3030             }
3031 
3032            //Pnum is >= 0 only if last loop was broken, meaning a player wasn't caught up
3033         if (pnum >= 0)
3034             break;
3035 
3036         domovethings();
3037 
3038         #if DEBUG
3039         //if (DemoSyncRecord)
3040         //    demosync_record();
3041         #endif
3042         }
3043 
3044     if (!InputMode && !PauseKeySet)
3045         MNU_CheckForMenus();
3046     }
3047 
3048 
InitPlayerGameSettings(void)3049 void InitPlayerGameSettings(void)
3050     {
3051     int pnum;
3052 
3053     // don't jack with auto aim settings if DemoMode is going
3054     // what the hell did I do this for?????????
3055     //if (DemoMode)
3056     //    return;
3057 
3058     if (CommEnabled)
3059         {
3060         // everyone gets the same Auto Aim
3061         TRAVERSE_CONNECT(pnum)
3062             {
3063             if (gNet.AutoAim)
3064                 SET(Player[pnum].Flags, PF_AUTO_AIM);
3065             else
3066                 RESET(Player[pnum].Flags, PF_AUTO_AIM);
3067             }
3068         }
3069     else
3070         {
3071         if (gs.AutoAim)
3072             SET(Player[myconnectindex].Flags, PF_AUTO_AIM);
3073         else
3074             RESET(Player[myconnectindex].Flags, PF_AUTO_AIM);
3075         }
3076 
3077     // everyone had their own Auto Run
3078     if (gs.AutoRun)
3079         SET(Player[myconnectindex].Flags, PF_LOCK_RUN);
3080     else
3081         RESET(Player[myconnectindex].Flags, PF_LOCK_RUN);
3082 
3083     if (gs.MouseAimingOn)
3084         SET(Player[myconnectindex].Flags, PF_MOUSE_AIMING_ON);
3085     else
3086         RESET(Player[myconnectindex].Flags, PF_MOUSE_AIMING_ON);
3087     }
3088 
3089 
InitRunLevel(VOID)3090 VOID InitRunLevel(VOID)
3091     {
3092     int i;
3093     if (DemoEdit)
3094         return;
3095 
3096     if (LoadGameOutsideMoveLoop)
3097         {
3098         int SavePlayClock;
3099         extern int PlayClock;
3100         LoadGameOutsideMoveLoop = FALSE;
3101         // contains what is needed from calls below
3102         if (gs.Ambient)
3103             StartAmbientSound();
3104         SetCrosshair();
3105         PlaySong(LevelSong, -1, TRUE, TRUE);
3106         SetRedrawScreen(Player + myconnectindex);
3107         // crappy little hack to prevent play clock from being overwritten
3108         // for load games
3109         SavePlayClock = PlayClock;
3110         InitTimingVars();
3111         PlayClock = SavePlayClock;
3112         MONO_PRINT("Done with InitRunLevel");
3113         return;
3114         }
3115 
3116     #if 0
3117         // ensure we are through the initialization code before sending the game
3118         // version. Otherwise, it is possible to send this too early and have it
3119         // blown away on the other side.
3120         waitforeverybody();
3121     #endif
3122 
3123     SendVersion(GameVersion);
3124 
3125     waitforeverybody();
3126 
3127     StopSong();
3128 
3129     if (Bstrcasecmp(CacheLastLevel, LevelName) != 0)
3130         DoTheCache();
3131 
3132     if (CachePrintMode)
3133         cachedebug = TRUE;
3134 
3135     // auto aim / auto run / etc
3136     InitPlayerGameSettings();
3137 
3138     // send packets with player info
3139     InitNetPlayerOptions();
3140 
3141     // Initialize Game part of network code (When ready2send != 0)
3142     InitNetVars();
3143 
3144     {
3145         int track;
3146         if (Level == 0) {
3147             track = RedBookSong[4+RANDOM_RANGE(10)];
3148         } else {
3149             track = RedBookSong[Level];
3150         }
3151         PlaySong(LevelSong, track, TRUE, TRUE);
3152     }
3153 
3154     InitPrediction(&Player[myconnectindex]);
3155 
3156     if (!DemoInitOnce)
3157         DemoRecordSetup();
3158 
3159     // everything has been inited at least once for RECORD
3160     DemoInitOnce = TRUE;
3161 
3162 //DebugWriteLoc(__FILE__, __LINE__);
3163     waitforeverybody();
3164 
3165     CheckVersion(GameVersion);
3166 
3167     // IMPORTANT - MUST be right before game loop AFTER waitforeverybody
3168     InitTimingVars();
3169 
3170     SetRedrawScreen(Player + myconnectindex);
3171 
3172     FX_SetVolume(gs.SoundVolume); // Turn volume back up
3173     if (gs.Ambient)
3174         StartAmbientSound();
3175     }
3176 
3177 VOID
RunLevel(VOID)3178 RunLevel(VOID)
3179     {
3180     int i;
3181     InitRunLevel();
3182 
3183     FX_SetVolume(gs.SoundVolume);
3184     SetSongVolume(gs.MusicVolume);
3185 
3186 #if 0
3187     waitforeverybody();
3188 #endif
3189     ready2send = 1;
3190 
3191     while (TRUE)
3192         {
3193         handleevents();
3194         OSD_DispatchQueued();
3195 
3196         if (quitevent)
3197             {
3198             if (CommPlayers >= 2)
3199                 MultiPlayQuitFlag = TRUE;
3200             else
3201                 QuitFlag = TRUE;
3202             }
3203 
3204           //MONO_PRINT("Before MoveLoop");
3205         MoveLoop();
3206         //MONO_PRINT("After MoveLoop");
3207         //MONO_PRINT("Before DrawScreen");
3208         drawscreen(Player + screenpeek);
3209         //MONO_PRINT("After DrawScreen");
3210 
3211         if (QuitFlag)
3212             break;
3213 
3214         if (ExitLevel)
3215             {
3216             ExitLevel = FALSE;
3217             break;
3218             }
3219         }
3220 
3221     ready2send = 0;
3222     }
3223 
swexit(int exitval)3224 void swexit(int exitval)
3225     {
3226     exit(exitval);
3227     }
3228 
DosScreen(VOID)3229 VOID DosScreen(VOID)
3230     {
3231 #if 0
3232     #ifdef SW_SHAREWARE
3233     #define DOS_SCREEN_NAME "SHADSW.BIN"
3234     #else
3235     #define DOS_SCREEN_NAME "SWREG.BIN"
3236     #endif
3237 
3238     #define DOS_SCREEN_SIZE (4000-(80*2))
3239     #define DOS_SCREEN_PTR ((void *)(0xB8000))
3240     int fin;
3241     int i;
3242     char buffer[DOS_SCREEN_SIZE];
3243 
3244     fin = kopen4load(DOS_SCREEN_NAME,0);
3245     if (fin == -1)
3246         return;
3247 
3248     kread(fin, buffer, sizeof(buffer));
3249     memcpy(DOS_SCREEN_PTR, buffer, DOS_SCREEN_SIZE);
3250     kclose(fin);
3251     move_cursor(23,0);
3252     _displaycursor( _GCURSORON );
3253 #endif
3254     }
3255 
AlphaMessage(VOID)3256 VOID AlphaMessage(VOID)
3257     {
3258     if (SW_SHAREWARE) {
3259         buildputs("SHADOW WARRIOR(tm) (Shareware Version)\n");
3260     } else {
3261         buildputs("SHADOW WARRIOR(tm)\n");
3262     }
3263     buildputs("Copyright (c) 1997 3D Realms Entertainment\n");
3264     }
3265 
3266 typedef struct
3267 {
3268 char    registered;
3269 char    *arg_fmt;
3270 char    *arg_descr;
3271 }CLI_ARG;
3272 
3273 #if DEBUG
3274 CLI_ARG cli_dbg_arg[] =
3275 {
3276 {0, "-coop#",               "Single Player Cooperative Mode"        },
3277 {0, "-commbat#",            "Single Player Commbat Mode"            },
3278 {0, "-demosyncrecord",      "Demo sync record"                      },
3279 {0, "-demosynctest",        "Demo sync test"                        },
3280 {0, "-cam",                 "Camera test mode"                      },
3281 {0, "-debugactor",          "No Actors"                             },
3282 {0, "-debuganim",           "No Anims"                              },
3283 {0, "-debugso",             "No Sector Objects"                     },
3284 {0, "-debugsector",         "No Sector Movement"                    },
3285 {0, "-debugpanel",          "No Panel"                              },
3286 {0, "-mono",                "Mono"                                  },
3287 {0, "-allsync",             "Enable full sync testing"              },
3288 };
3289 #endif
3290 
3291 
3292 CLI_ARG cli_arg[] =
3293 {
3294 {0, "-?",                   "This help message"                     },
3295 #if DEBUG
3296 {0, "-debug",               "Debug Help Options"                    },
3297 #endif
3298 {1, "-map [mapname]",       "Load a map"                            },
3299 {1, "-nocd<audio>",         "No CD Red Book Audio"                  },
3300 {0, "-name [playername]",   "Player Name"                           },
3301 {0, "-s#",                  "Skill (1-4)"                           },
3302 {0, "-f#",                  "Packet Duplication - 2, 4, 8"          },
3303 {0, "-nopred<ict>",         "Disable Net Prediction Method"         },
3304 {0, "-level#",              "Start at level# (Shareware: 1-4, full version 1-28)" },
3305 {0, "-dr[filename.dmo]",    "Demo record. NOTE: Must use -level# with this option." },
3306 {0, "-dp[filename.dmo]",    "Demo playback. NOTE: Must use -level# with this option." },
3307 {0, "-monst<ers>",          "No Monsters"                           },
3308 {0, "-nodemo",              "No demos on game startup"              },
3309 {0, "-nometers",            "Don't show air or boss meter bars in game"},
3310 {0, "-movescale [sc]",      "Adjust movement scale: 256 = 1 unit"   },
3311 {0, "-turnscale [sc]",      "Adjust turning scale: 256 = 1 unit"    },
3312 {0, "-extcompat",           "Controller compatibility mode (with Duke 3D)"},
3313 {1, "-g[filename.grp]",     "Load an extra GRP or ZIP file"         },
3314 {1, "-h[filename.def]",     "Use filename.def instead of SW.DEF"    },
3315 {0, "-setup",               "Displays the configuration dialogue box"},
3316 {0, "-nosetup",             "Prevents display of the configuration dialogue box"},
3317 
3318 #if 0 //def NET_MODE_MASTER_SLAVE
3319 {0, "-broad<cast>",         "Broadcast network method (default)"    },
3320 {0, "-master<slave>",       "Master/Slave network method"           },
3321 #endif
3322 };
3323 
3324 /*
3325 Map       ->    User Map Name
3326 Auto      ->    Auto Start Game
3327 Rules     ->    0=WangBang 1=WangBang (No Respawn) 2=CoOperative
3328 Level     ->    0 to 24(?)
3329 Enemy     ->    0=None 1=Easy 2=Norm 3=Hard 4=Insane
3330 Markers   ->    0=Off 1=On
3331 Team      ->    0=Off 1=On
3332 HurtTeam  ->    0=Off 1=On
3333 KillLimit ->    0=Infinite 1=10 2=20 3=30 4=40 5=50 6=60 7=70 8=80 9=90 10=100
3334 TimeLimit ->    0=Infinite 1=3 2=5 3=10 4=20 5=30 6=45 7=60
3335 Color     ->    0=Brown 1=Purple 2=Red 3=Yellow 4=Olive 5=Green
3336 Nuke      ->    0=Off 1=On
3337 
3338 Example Command Line:
3339 sw -map testmap.map -autonet 0,0,1,1,1,0,3,2,1,1 -f4 -name 1234567890 -net 12345678
3340 commit -map grenade -autonet 0,0,1,1,1,0,3,2,1,1 -name frank
3341 */
3342 
3343 char isShareware = FALSE, useDarts = FALSE;
3344 
DetectShareware(void)3345 int DetectShareware(void)
3346     {
3347     #define DOS_SCREEN_NAME_SW  "SHADSW.BIN"
3348     #define DOS_SCREEN_NAME_REG "SWREG.BIN"
3349 
3350     int h;
3351 
3352     h = kopen4load(DOS_SCREEN_NAME_SW,1);
3353     if (h >= 0)
3354         {
3355         isShareware = TRUE;
3356         kclose(h);
3357         return 0;
3358         }
3359 
3360     h = kopen4load(DOS_SCREEN_NAME_REG,1);
3361     if (h >= 0)
3362         {
3363         isShareware = FALSE;
3364         kclose(h);
3365         return 0;
3366         }
3367 
3368     return 1;   // heavens knows what this is...
3369     }
3370 
3371 
CommandLineHelp(CLI_ARG * args,int numargs)3372 void CommandLineHelp(CLI_ARG *args, int numargs)
3373     {
3374     int i;
3375 
3376     const char *usagefmt = "Usage: %s [options]\n";
3377     const char *optionsfmt = "options:  (%s)\n\n";
3378 #ifdef _WIN32
3379     const char *argfmt = "%s\t%s\n";
3380     const char *strargv0 = "sw";
3381     const char *stropts = "'/' may be used instead of '-', <> text is optional";
3382 #else
3383     #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199409L
3384     const char *argfmt = " %s  \u2014  %s\n";
3385     #else
3386     const char *argfmt = " %s  --  %s\n";
3387     #endif
3388     const char *strargv0 = _buildargv[0];
3389     const char *stropts = "<> text is optional";
3390 #endif
3391 
3392     char *str = NULL, *strapp;
3393     int len;
3394 
3395     len = snprintf(NULL, 0, usagefmt, strargv0);
3396     len += snprintf(NULL, 0, optionsfmt, stropts);
3397     for (i=0;i < numargs;i++)
3398         {
3399         if (!args[i].arg_fmt || args[i].registered > SW_REGISTERED)
3400             continue;
3401         len += snprintf(NULL, 0, argfmt, args[i].arg_fmt, args[i].arg_descr);
3402         }
3403 
3404     if (len < 0 || !(str = (char *)malloc(len + 1)))
3405         {
3406         wm_msgbox("Shadow Warrior Help", "Command line help not available");
3407         return;
3408         }
3409 
3410     strapp = str;
3411     strapp += sprintf(strapp, usagefmt, strargv0);
3412     strapp += sprintf(strapp, optionsfmt, stropts);
3413     for (i=0;i < numargs;i++)
3414         {
3415         if (!args[i].arg_fmt || args[i].registered > SW_REGISTERED)
3416             continue;
3417         strapp += sprintf(strapp, argfmt, args[i].arg_fmt, args[i].arg_descr);
3418         }
3419 
3420         wm_msgbox("Shadow Warrior Help", "%s", str);
3421         free(str);
3422     }
3423 
3424 char grpfile[BMAX_PATH+1] = "sw.grp";
3425 const char *gameeditionname = "Unknown edition";
3426 
app_main(int argc,char const * const argv[])3427 int app_main(int argc, char const * const argv[])
3428     {
3429     int i;
3430     int stat, nexti;
3431     char type;
3432     extern int MovesPerPacket;
3433     VOID DoSector(VOID);
3434     VOID gameinput(VOID);
3435     int cnt = 0;
3436     int netparam = 0, endnetparam = 0;
3437     ULONG TotalMemory;
3438     int configloaded;
3439     struct grpfile *gamegrp = NULL;
3440 
3441 #ifdef RENDERTYPEWIN
3442     if (win_checkinstance()) {
3443         if (!wm_ynbox("Shadow Warrior","Another Build game is currently running. "
3444                     "Do you wish to continue starting this copy?"))
3445             return 0;
3446     }
3447 #endif
3448 
3449 #if defined(DATADIR)
3450     {
3451         const char *datadir = DATADIR;
3452         if (datadir && datadir[0]) {
3453             addsearchpath(datadir);
3454         }
3455     }
3456 #endif
3457 
3458     {
3459         char *supportdir = Bgetsupportdir(TRUE);
3460         char *appdir = Bgetappdir();
3461         char dirpath[BMAX_PATH+1];
3462 
3463         // the OSX app bundle, or on Windows the directory where the EXE was launched
3464         if (appdir) {
3465             addsearchpath(appdir);
3466             free(appdir);
3467         }
3468 
3469         // the global support files directory
3470         if (supportdir) {
3471             Bsnprintf(dirpath, sizeof(dirpath), "%s/JFShadowWarrior", supportdir);
3472             addsearchpath(dirpath);
3473             free(supportdir);
3474         }
3475     }
3476 
3477     // default behaviour is to write to the user profile directory, but
3478     // creating a 'user_profiles_disabled' file in the current working
3479     // directory where the game was launched makes the installation
3480     // "portable" by writing into the working directory
3481     if (access("user_profiles_disabled", F_OK) == 0) {
3482         char cwd[BMAX_PATH+1];
3483         if (getcwd(cwd, sizeof(cwd))) {
3484             addsearchpath(cwd);
3485         }
3486     } else {
3487         char *supportdir;
3488         char dirpath[BMAX_PATH+1];
3489         int asperr;
3490 
3491         if ((supportdir = Bgetsupportdir(FALSE))) {
3492 #if defined(_WIN32) || defined(__APPLE__)
3493             const char *confdir = "JFShadowWarrior";
3494 #else
3495             const char *confdir = ".jfsw";
3496 #endif
3497             Bsnprintf(dirpath, sizeof(dirpath), "%s/%s", supportdir, confdir);
3498             asperr = addsearchpath(dirpath);
3499             if (asperr == -2) {
3500                 if (Bmkdir(dirpath, S_IRWXU) == 0) {
3501                     asperr = addsearchpath(dirpath);
3502                 } else {
3503                     asperr = -1;
3504                 }
3505             }
3506             if (asperr == 0) {
3507                 chdir(dirpath);
3508             }
3509             free(supportdir);
3510         }
3511     }
3512 
3513     buildsetlogfile("sw.log");
3514 
3515     OSD_RegisterFunction("restartvid", "restartvid: reinitialise the video mode", osdcmd_restartvid);
3516     OSD_RegisterFunction("vidmode", "vidmode [xdim ydim] [bpp] [fullscreen]: change the video mode", osdcmd_vidmode);
3517 
3518     wm_setapptitle("JFShadowWarrior");
3519     buildprintf("\nJFShadowWarrior\n"
3520         "Based on Shadow Warrior by 3D Realms Entertainment.\n"
3521         "Additional improvements by Jonathon Fowler (http://www.jonof.id.au) and other contributors.\n"
3522         "See GPL.TXT for license terms.\n\n"
3523         "Version %s.\nBuilt %s %s.\n", game_version, game_date, game_time);
3524 
3525     for (i=1;i<argc;i++) {
3526         char const *arg = argv[i];
3527 
3528 #ifdef _WIN32
3529         if (*arg != '-' && *arg != '/') continue;
3530 #else
3531         if (*arg != '-') continue;
3532 #endif
3533 
3534         arg++;
3535         if (!Bstrcasecmp(arg, "setup"))
3536             {
3537             CommandSetup = 1;
3538             }
3539         else
3540         if (!Bstrcasecmp(arg, "nosetup"))
3541             {
3542             CommandSetup = -1;
3543             }
3544         else
3545         if (!Bstrcasecmp(arg, "net"))
3546             {
3547             netparam = ++i;
3548             for (; i<argc; i++)
3549                 if (!strcmp(argv[i], "--")) break;
3550             endnetparam = i;
3551             }
3552         else
3553         if (!Bstrcasecmp(arg, "?"))
3554             {
3555             CommandLineHelp(cli_arg, SIZ(cli_arg));
3556             return(0);
3557             }
3558 #if DEBUG
3559         else
3560         if (!Bstrcasecmp(arg, "debug"))
3561             {
3562             CommandLineHelp(cli_dbg_arg, SIZ(cli_dbg_arg));
3563             return(0);
3564             }
3565 #endif
3566     }
3567 
3568     if (preinitengine()) {
3569        wm_msgbox("Build Engine Initialisation Error",
3570                "There was a problem initialising the Build engine: %s", engineerrstr);
3571        exit(1);
3572     }
3573 
3574     configloaded = CONFIG_ReadSetup();
3575     if (getenv("SWGRP")) {
3576         strncpy(grpfile, getenv("SWGRP"), BMAX_PATH);
3577     }
3578 
3579     ScanGroups();
3580     {
3581         // Try and identify grpfile in the set of GRPs.
3582         struct grpfile *first = NULL;
3583         for (gamegrp = foundgrps; gamegrp; gamegrp = gamegrp->next) {
3584             if (!gamegrp->ref) continue;     // Not a recognised game file.
3585             if (!first) first = gamegrp;
3586             if (!Bstrcasecmp(gamegrp->name, grpfile)) {
3587                 // Found it.
3588                 break;
3589             }
3590         }
3591         if (!gamegrp && first) {
3592             // It wasn't found, so use the first recognised one scanned.
3593             gamegrp = first;
3594         }
3595     }
3596 
3597     if (netparam) { // -net parameter on command line.
3598         netsuccess = initmultiplayersparms(endnetparam - netparam, &argv[netparam]);
3599     }
3600 
3601 #if defined RENDERTYPEWIN || (defined RENDERTYPESDL && (defined __APPLE__ || defined HAVE_GTK))
3602     {
3603         struct startwin_settings settings;
3604 
3605         memset(&settings, 0, sizeof(settings));
3606         settings.fullscreen = ScreenMode;
3607         settings.xdim3d = ScreenWidth;
3608         settings.ydim3d = ScreenHeight;
3609         settings.bpp3d = ScreenBPP;
3610         settings.forcesetup = ForceSetup;
3611         settings.usemouse = UseMouse;
3612         settings.usejoy = UseJoystick;
3613         settings.samplerate = MixRate;
3614         settings.bitspersample = NumBits;
3615         settings.channels = NumChannels;
3616         settings.selectedgrp = gamegrp;
3617         settings.netoverride = netparam > 0;
3618 
3619         if (configloaded < 0 || (ForceSetup && CommandSetup == 0) || (CommandSetup > 0)) {
3620             if (startwin_run(&settings) == STARTWIN_CANCEL) {
3621                 uninitengine();
3622                 exit(0);
3623             }
3624         }
3625 
3626         ScreenMode = settings.fullscreen;
3627         ScreenWidth = settings.xdim3d;
3628         ScreenHeight = settings.ydim3d;
3629         ScreenBPP = settings.bpp3d;
3630         ForceSetup = settings.forcesetup;
3631         UseMouse = settings.usemouse;
3632         UseJoystick = settings.usejoy;
3633         MixRate = settings.samplerate;
3634         NumBits = settings.bitspersample;
3635         NumChannels = settings.channels;
3636         gamegrp = settings.selectedgrp;
3637 
3638         if (!netparam) {
3639             char modeparm[8];
3640             const char *parmarr[3] = { modeparm, NULL, NULL };
3641             int parmc = 0;
3642 
3643             if (settings.joinhost) {
3644                 strcpy(modeparm, "-nm");
3645                 parmarr[1] = settings.joinhost;
3646                 parmc = 2;
3647             } else if (settings.numplayers > 1 && settings.numplayers <= MAXPLAYERS) {
3648                 sprintf(modeparm, "-nm:%d", settings.numplayers);
3649                 parmc = 1;
3650             }
3651 
3652             if (parmc > 0) {
3653                 netsuccess = initmultiplayersparms(parmc, parmarr);
3654             }
3655 
3656             if (settings.joinhost) {
3657                 free(settings.joinhost);
3658             }
3659         }
3660     }
3661 #endif
3662 
3663     if (gamegrp) {
3664         Bstrcpy(grpfile, gamegrp->name);
3665         gameeditionname = gamegrp->ref->name;  // Points to static data, so won't be lost in FreeGroups().
3666     }
3667 
3668     FreeGroups();
3669 
3670     buildprintf("GRP file: %s\n", grpfile);
3671     initgroupfile(grpfile);
3672     if (!DetectShareware()) {
3673         if (SW_SHAREWARE) {
3674             buildputs("Detected shareware GRP\n");
3675         } else {
3676             buildputs("Detected registered GRP\n");
3677         }
3678     }
3679 
3680     buildputs("\n");
3681     AlphaMessage();
3682     buildputs("\n");
3683 
3684     if (SW_SHAREWARE) {
3685         // Zero out the maps that aren't in shareware version
3686         memset(&LevelInfo[MAX_LEVELS_SW+1], 0, sizeof(LEVEL_INFO)*(MAX_LEVELS_REG-MAX_LEVELS_SW));
3687         GameVersion++;
3688     }
3689 
3690     for (i = 0; i < MAX_SW_PLAYERS; i++)
3691         INITLIST(&Player[i].PanelSpriteList);
3692 
3693     DebugOperate = TRUE;
3694 
3695     UserMapName[0] = '\0';
3696 
3697     //LocationInfo = TRUE;
3698 
3699     #if 0
3700     //#if DEBUG && SYNC_TEST
3701     // automatically record a demo
3702     DemoRecording = TRUE;
3703     DemoPlaying = FALSE;
3704     PreCaching = TRUE;
3705     DemoRecCnt = 0;
3706     strcpy(DemoFileName, "DMOTEST.DMO");
3707     //DemoSyncRecord = TRUE;
3708     #endif
3709 
3710     #if DEBUG
3711     {
3712     FILE *fout;
3713     if ((fout = fopen("dbg.foo", "wb")) != NULL)
3714         {
3715         fprintf(fout, "Whoo-oo-ooooo wants some wang?\n");
3716         fclose(fout);
3717         }
3718     }
3719     #endif
3720 
3721     for (cnt = 1; cnt < argc; cnt++)
3722         {
3723         char const *arg = argv[cnt];
3724 
3725 #ifdef _WIN32
3726         if (*arg != '/' && *arg != '-') continue;
3727 #else
3728         if (*arg != '-') continue;
3729 #endif
3730 
3731         // Store arg in command line array!
3732         CON_StoreArg(arg);
3733         arg++;
3734 
3735         if (Bstrcasecmp(arg, "net") == 0)
3736             {
3737             for (; i<argc; i++)
3738                 if (!strcmp(argv[i], "--")) break;
3739             }
3740         else
3741         if (Bstrncasecmp(arg, "autonet",7) == 0)
3742             {
3743             AutoNet = TRUE;
3744             cnt++;
3745             sscanf(argv[cnt],"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",&Auto.Rules,&Auto.Level,&Auto.Enemy,&Auto.Markers,
3746                 &Auto.Team,&Auto.HurtTeam,&Auto.Kill,&Auto.Time,&Auto.Color,&Auto.Nuke);
3747             }
3748         else
3749         if (Bstrncasecmp(arg, "turnscale",9) == 0)
3750             {
3751             if (cnt <= argc-2)
3752                 {
3753                 cnt++;
3754                 sscanf(argv[cnt], "%d",&turn_scale);
3755                 }
3756             }
3757         else
3758         if (Bstrncasecmp(arg, "movescale",9) == 0)
3759             {
3760             if (cnt <= argc-2)
3761                 {
3762                 cnt++;
3763                 sscanf(argv[cnt], "%d",&move_scale);
3764                 }
3765             }
3766         else
3767         if (Bstrncasecmp(arg, "extcompat",9) == 0)
3768             {
3769             move_scale *= 5;
3770             turn_scale *= 5;
3771             }
3772         else
3773         if (Bstrncasecmp(arg, "cacheprint",10) == 0)
3774             {
3775             CachePrintMode = TRUE;
3776             }
3777         else
3778         if (Bstrncasecmp(arg, "setupfile",8) == 0)
3779             {
3780             // Passed by setup.exe
3781             // skip setupfile name
3782             cnt++;
3783             }
3784         else
3785         if (Bstrncasecmp(arg, "short",5) == 0)
3786             {
3787             ShortGameMode = TRUE;
3788             }
3789         else
3790         if (Bstrncasecmp(arg, "nodemo",6) == 0)
3791             {
3792             NoDemoStartup = TRUE;
3793             }
3794 #if DEBUG
3795         else
3796         if (Bstrncasecmp(arg, "allsync",3) == 0)
3797             {
3798             NumSyncBytes = MAXSYNCBYTES;
3799             }
3800 #endif
3801         else
3802         if (Bstrncasecmp(arg, "name",4) == 0)
3803             {
3804             if (cnt <= argc-2)
3805                 {
3806                 strncpy(CommPlayerName, argv[++cnt], SIZ(CommPlayerName)-1);
3807                 CommPlayerName[SIZ(CommPlayerName)-1] = '\0';
3808                 }
3809             }
3810         else
3811         if (Bstrncasecmp(arg, "f8",2) == 0)
3812             {
3813             MovesPerPacket = 8;
3814             }
3815         else
3816         if (Bstrncasecmp(arg, "f4",2) == 0)
3817             {
3818             MovesPerPacket = 4;
3819             }
3820         else
3821         if (Bstrncasecmp(arg, "f2",2) == 0)
3822             {
3823             MovesPerPacket = 2;
3824             }
3825         else
3826         if (Bstrncasecmp(arg, "monst", 5) == 0)
3827             {
3828             DebugActor = TRUE;
3829             }
3830         else
3831         if (Bstrncasecmp(arg, "nopredict",6) == 0)
3832             {
3833             extern BOOL PredictionOn;
3834             PredictionOn = FALSE;
3835             }
3836                 else
3837         if (Bstrncasecmp(arg, "col", 3) == 0)
3838                 // provides a way to force the player color for joiners
3839                 // since -autonet does not seem to work for them
3840             {
3841                         int temp;
3842             cnt++;
3843             sscanf(argv[cnt],"%d",&temp);
3844                         AutoColor = temp;
3845                         HasAutoColor = TRUE;
3846             }
3847         else
3848         if (Bstrncasecmp(arg, "level", 5) == 0)
3849             {
3850             if (strlen(arg) > 5)
3851                 {
3852                 strcpy(UserMapName,LevelInfo[atoi(&arg[5])].LevelName);
3853                 }
3854             }
3855         else
3856         if (Bstrncasecmp(arg, "s", 1) == 0)
3857             {
3858             if (strlen(arg) > 1)
3859                 Skill = atoi(&arg[1])-1;
3860 
3861             Skill = max(Skill,0);
3862             Skill = min(Skill,3);
3863             }
3864         else
3865         if (Bstrncasecmp(arg, "nometers", 8) == 0)
3866             {
3867             NoMeters = TRUE;
3868             }
3869         else
3870 #if DEBUG
3871         if (Bstrncasecmp(arg, "commbat", 7) == 0)
3872             {
3873             if (strlen(arg) > 7)
3874                 {
3875                 FakeMultiNumPlayers = atoi(&arg[7]);
3876                 gNet.MultiGameType = MULTI_GAME_COMMBAT;
3877                 }
3878             }
3879         else
3880         if (Bstrncasecmp(arg, "coop", 4) == 0)
3881             {
3882             if (strlen(arg) > 4)
3883                 {
3884                 FakeMultiNumPlayers = atoi(&arg[4]);
3885                 gNet.MultiGameType = MULTI_GAME_COOPERATIVE;
3886                 }
3887             }
3888         else
3889         if (Bstrncasecmp(arg, "bots", 4) == 0)
3890             {
3891             if (strlen(arg) > 4)
3892                 {
3893                 FakeMultiNumPlayers = atoi(&arg[4]);
3894                 printf("Adding %d BOT(s) to the game!\n",FakeMultiNumPlayers);
3895                 gNet.MultiGameType = MULTI_GAME_AI_BOTS;
3896                 BotMode = TRUE;
3897                 }
3898             }
3899         else
3900         if (Bstrncasecmp(arg, "ddr", 3) == 0)
3901             {
3902             //NumSyncBytes = 8;
3903             DemoRecording = TRUE;
3904             DemoPlaying = FALSE;
3905             DemoRecCnt = 0;
3906             DemoDebugMode = TRUE;
3907 
3908             if (strlen(arg) > 3)
3909                 {
3910                 strcpy(DemoFileName, &arg[2]);
3911                 if (strchr(DemoFileName, '.') == 0)
3912                     strcat(DemoFileName, ".dmo");
3913                 }
3914             }
3915         else
3916 #endif
3917         if (Bstrncasecmp(arg, "dr", 2) == 0)
3918             {
3919             //NumSyncBytes = 8;
3920             DemoRecording = TRUE;
3921             DemoPlaying = FALSE;
3922             DemoRecCnt = 0;
3923 
3924             if (strlen(arg) > 2)
3925                 {
3926                 strcpy(DemoFileName, &arg[2]);
3927                 if (strchr(DemoFileName, '.') == 0)
3928                     strcat(DemoFileName, ".dmo");
3929                 }
3930             }
3931         else
3932         if (Bstrncasecmp(arg, "dp", 2) == 0)
3933             {
3934             DemoPlaying = TRUE;
3935             DemoRecording = FALSE;
3936             PreCaching = TRUE;
3937 
3938             if (strlen(arg) > 2)
3939                 {
3940                 strcpy(DemoFileName, &arg[2]);
3941                 if (strchr(DemoFileName, '.') == 0)
3942                     strcat(DemoFileName, ".dmo");
3943                 }
3944             }
3945 
3946         #if 0 //def NET_MODE_MASTER_SLAVE
3947         else
3948         if (Bstrncasecmp(arg, "masterslave",6) == 0)
3949             {
3950             NetModeOverride = TRUE;
3951             NetBroadcastMode = FALSE;
3952             }
3953         else
3954         if (Bstrncasecmp(arg, "broadcast",5) == 0)
3955             {
3956             NetModeOverride = TRUE;
3957             NetBroadcastMode = TRUE;
3958             }
3959         #endif
3960 
3961         else
3962         if (Bstrncasecmp(arg, "cheat",5) == 0)
3963             {
3964             ArgCheat = TRUE;
3965             }
3966         else
3967         if (Bstrncasecmp(arg, "demosynctest",12) == 0)
3968             {
3969             NumSyncBytes = 8;
3970             DemoSyncTest = TRUE;
3971             DemoSyncRecord = FALSE;
3972             }
3973         else
3974         if (Bstrncasecmp(arg, "demosyncrecord",12) == 0)
3975             {
3976             NumSyncBytes = 8;
3977             DemoSyncTest = FALSE;
3978             DemoSyncRecord = TRUE;
3979             }
3980 #if DEBUG
3981         else
3982         if (Bstrncasecmp(arg, "cam",3) == 0)
3983             {
3984             CameraTestMode = TRUE;
3985             }
3986         else
3987         if (FALSE && Bstrncasecmp(arg, "de", 2) == 0)
3988             {
3989             #if DEMO_FILE_TYPE == DEMO_FILE_GROUP
3990             DemoPlaying = TRUE;
3991             DemoRecording = FALSE;
3992 
3993             if (strlen(arg) > 2)
3994                 {
3995                 strcpy(DemoFileName, &arg[2]);
3996                 if (strchr(DemoFileName, '.') == 0)
3997                     strcat(DemoFileName, ".dmo");
3998                 }
3999             #else
4000             DemoEdit = TRUE;
4001             DemoPlaying = TRUE;
4002             DemoRecording = FALSE;
4003 
4004             if (strlen(arg) > 2)
4005                 {
4006                 strcpy(DemoFileName, &arg[2]);
4007                 if (strchr(DemoFileName, '.') == 0)
4008                     strcat(DemoFileName, ".dmo");
4009                 }
4010             #endif
4011             }
4012         else
4013         if (Bstrncasecmp(arg, "randprint",5) == 0)
4014             {
4015             RandomPrint = TRUE;
4016             }
4017         else
4018         if (Bstrncasecmp(arg, "level", 5) == 0)
4019             {
4020             if (strlen(arg) > 5)
4021                 {
4022                 strcpy(UserMapName,LevelInfo[atoi(&arg[5])].LevelName);
4023                 }
4024             }
4025         else
4026         if (Bstrncasecmp(arg, "debugsecret", 10) == 0)
4027             {
4028             extern BOOL DebugSecret;
4029             DebugSecret = TRUE;
4030             }
4031         else
4032         if (Bstrncasecmp(arg, "debugactor", 10) == 0)
4033             {
4034             DebugActor = TRUE;
4035             }
4036         else
4037         if (Bstrncasecmp(arg, "mono", 4) == 0)
4038             {
4039             DispMono = TRUE;
4040             }
4041         else
4042         if (Bstrncasecmp(arg, "debugso", 7) == 0)
4043             {
4044             DebugSO = TRUE;
4045             }
4046         else
4047         if (Bstrncasecmp(arg, "nosyncprint",10) == 0)
4048             {
4049             extern BOOL SyncPrintMode;
4050             SyncPrintMode = FALSE;
4051             }
4052         else
4053         if (Bstrncasecmp(arg, "debuganim", 9) == 0)
4054             {
4055             DebugAnim = TRUE;
4056             }
4057         else
4058         if (Bstrncasecmp(arg, "debugsector", 11) == 0)
4059             {
4060             DebugSector = TRUE;
4061             }
4062         else
4063         if (Bstrncasecmp(arg, "debugpanel", 10) == 0)
4064             {
4065             DebugPanel = TRUE;
4066             }
4067         else
4068         if (FALSE && Bstrncasecmp(arg, "dt", 2) == 0)
4069             {
4070             if (strlen(arg) > 2)
4071                 {
4072                 strcpy(DemoTmpName, &arg[2]);
4073                 if (strchr(DemoFileName, '.') == 0)
4074                     strcat(DemoFileName, ".dmo");
4075                 }
4076             }
4077         else
4078         if (Bstrncasecmp(arg, "nodemo", 6) == 0)
4079             {
4080             DemoRecording = FALSE;
4081             DemoPlaying = FALSE;
4082             PreCaching = TRUE;
4083             DemoRecCnt = 0;
4084 
4085             DemoSyncTest = FALSE;
4086             DemoSyncRecord = FALSE;
4087             }
4088 #endif
4089 
4090         else
4091         if (Bstrncasecmp(arg, "map", 3) == 0)
4092             {
4093             int fil;
4094 
4095             strcpy(UserMapName, argv[++cnt]);
4096             if (strchr(UserMapName, '.') == 0)
4097                 strcat(UserMapName, ".map");
4098 
4099             if ((fil = kopen4load(UserMapName,0)) == -1)
4100                 {
4101                 kclose(fil);
4102                 wm_msgbox(NULL, "ERROR: Could not find user map %s!",UserMapName);
4103                 swexit(0);
4104                 }
4105             else
4106                 kclose(fil);
4107             }
4108 
4109         else
4110         if (Bstrncasecmp(arg, "g", 1) == 0)
4111             {
4112             if (strlen(arg) > 1)
4113                 {
4114                 if (initgroupfile(arg+1) >= 0)
4115                     buildprintf("Added %s\n", arg+1);
4116                 }
4117             }
4118         else
4119         if (Bstrncasecmp(arg, "h", 1) == 0)
4120             {
4121             if (strlen(arg) > 1)
4122                 {
4123                 deffile = (arg+1);
4124                 buildprintf("Using DEF file %s.\n", arg+1);
4125                 }
4126             }
4127         }
4128 
4129     Control();
4130 
4131     return (0);
4132     }
4133 
4134 VOID
ManualPlayerInsert(PLAYERp pp)4135 ManualPlayerInsert(PLAYERp pp)
4136     {
4137     PLAYERp npp = Player + numplayers;
4138     int i;
4139 
4140     if (numplayers < MAX_SW_PLAYERS)
4141         {
4142         connectpoint2[numplayers - 1] = numplayers;
4143         connectpoint2[numplayers] = -1;
4144 
4145         npp->posx = pp->posx;
4146         npp->posy = pp->posy;
4147         npp->posz = pp->posz;
4148         npp->pang = pp->pang;
4149         npp->cursectnum = pp->cursectnum;
4150 
4151         myconnectindex = numplayers;
4152         screenpeek = numplayers;
4153 
4154         sprintf(Player[myconnectindex].PlayerName,"PLAYER %d",myconnectindex+1);
4155 
4156         Player[numplayers].movefifoend = Player[0].movefifoend;
4157 
4158         // If IsAI = TRUE, new player will be a bot
4159         Player[myconnectindex].IsAI = FALSE;
4160 
4161         CommPlayers++;
4162         numplayers++;
4163         }
4164 
4165     }
4166 
4167 VOID
BotPlayerInsert(PLAYERp pp)4168 BotPlayerInsert(PLAYERp pp)
4169     {
4170     PLAYERp npp = Player + numplayers;
4171     int i;
4172 
4173     if (numplayers < MAX_SW_PLAYERS)
4174         {
4175         connectpoint2[numplayers - 1] = numplayers;
4176         connectpoint2[numplayers] = -1;
4177 
4178         npp->posx = pp->posx;
4179         npp->posy = pp->posy;
4180         npp->posz = pp->posz-Z(100);
4181         npp->pang = pp->pang;
4182         npp->cursectnum = pp->cursectnum;
4183 
4184         //myconnectindex = numplayers;
4185         //screenpeek = numplayers;
4186 
4187         sprintf(Player[numplayers].PlayerName,"BOT %d",numplayers+1);
4188 
4189         Player[numplayers].movefifoend = Player[0].movefifoend;
4190 
4191         // If IsAI = TRUE, new player will be a bot
4192         Player[numplayers].IsAI = TRUE;
4193 
4194         CommPlayers++;
4195         numplayers++;
4196         }
4197 
4198 //    SetFragBar(pp);
4199     }
4200 
4201 VOID
ManualPlayerDelete(PLAYERp cur_pp)4202 ManualPlayerDelete(PLAYERp cur_pp)
4203     {
4204     short i, nexti;
4205     USERp u;
4206     short save_myconnectindex;
4207     PLAYERp pp;
4208 
4209     if (numplayers > 1)
4210         {
4211         CommPlayers--;
4212         numplayers--;
4213         connectpoint2[numplayers - 1] = -1;
4214 
4215         pp = Player + numplayers;
4216 
4217         KillSprite(pp->PlayerSprite);
4218         pp->PlayerSprite = -1;
4219 
4220         // Make sure enemys "forget" about deleted player
4221         TRAVERSE_SPRITE_STAT(headspritestat[STAT_ENEMY], i, nexti)
4222             {
4223             u = User[i];
4224             if (u->tgt_sp == pp->SpriteP)
4225                 u->tgt_sp = Player[0].SpriteP;
4226             }
4227 
4228         if (myconnectindex >= numplayers)
4229             myconnectindex = 0;
4230 
4231         if (screenpeek >= numplayers)
4232             screenpeek = 0;
4233         }
4234     }
4235 
4236 #if DEBUG
4237 VOID
SinglePlayInput(PLAYERp pp)4238 SinglePlayInput(PLAYERp pp)
4239     {
4240     int pnum = myconnectindex;
4241     BYTEp kp;
4242 
4243     if (BUTTON(gamefunc_See_Co_Op_View) && !UsingMenus && !ConPanel && dimensionmode == 3)
4244         {
4245         short oldscreenpeek = screenpeek;
4246 
4247         CONTROL_ClearButton(gamefunc_See_Co_Op_View);
4248         NextScreenPeek();
4249 
4250         if (dimensionmode == 2 || dimensionmode == 5 || dimensionmode == 6)
4251             setup2dscreen();
4252 
4253         if (dimensionmode != 2)
4254             {
4255             PLAYERp tp;
4256 
4257             tp = Player + screenpeek;
4258             PlayerUpdatePanelInfo(tp);
4259         if (getrendermode() < 3)
4260             COVERsetbrightness(gs.Brightness,(char *)palette_data);
4261         else
4262         setpalettefade(0,0,0,0);
4263             memcpy(pp->temp_pal, palette_data, sizeof(palette_data));
4264             DoPlayerDivePalette(tp);
4265             DoPlayerNightVisionPalette(tp);
4266 //          printf("SingPlayInput set_pal: tp->PlayerSprite = %d\n",tp->PlayerSprite);
4267             }
4268         }
4269 
4270     if (!(KEY_PRESSED(KEYSC_ALT) | KEY_PRESSED(KEYSC_RALT)))
4271         return;
4272 
4273 
4274     if (!SW_SHAREWARE && KEY_PRESSED(KEYSC_M))
4275         {
4276         extern BOOL DebugActorFreeze;
4277 
4278         KEY_PRESSED(KEYSC_M) = 0;
4279         DebugActorFreeze++;
4280         if (DebugActorFreeze > 2)
4281             DebugActorFreeze = 0;
4282 
4283         if (DebugActorFreeze == 2)
4284             {
4285             short i, nexti;
4286 
4287             TRAVERSE_SPRITE_STAT(headspritestat[STAT_ENEMY], i, nexti)
4288                 {
4289                 SET(sprite[i].cstat, CSTAT_SPRITE_INVISIBLE);
4290                 if (TEST(sprite[i].cstat, CSTAT_SPRITE_BLOCK))
4291                     {
4292                     SET(sprite[i].extra, SPRX_BLOCK);
4293                     RESET(sprite[i].cstat, CSTAT_SPRITE_BLOCK);
4294                     }
4295                 }
4296             }
4297 
4298         if (DebugActorFreeze == 0)
4299             {
4300             short i, nexti;
4301 
4302             TRAVERSE_SPRITE_STAT(headspritestat[STAT_ENEMY], i, nexti)
4303                 {
4304                 RESET(sprite[i].cstat, CSTAT_SPRITE_INVISIBLE);
4305                 if (TEST(sprite[i].extra, SPRX_BLOCK))
4306                     SET(sprite[i].cstat, CSTAT_SPRITE_BLOCK);
4307                 }
4308             }
4309         }
4310 
4311 
4312     // Insert a player
4313     if (KEY_PRESSED(KEYSC_INS))
4314         // player
4315         {
4316         KEY_PRESSED(KEYSC_INS) = 0;
4317         ManualPlayerInsert(pp);
4318         // comes back looking through screenpeek
4319         InitPlayerSprite(Player + screenpeek);
4320         PlayerDeathReset(Player + screenpeek);
4321         SetFragBar(pp);
4322         }
4323 
4324 
4325     // Delete a player
4326     if (KEY_PRESSED(KEYSC_DEL))
4327         {
4328         KEY_PRESSED(KEYSC_DEL) = 0;
4329         ManualPlayerDelete(pp);
4330         }
4331 
4332     // Move control to numbered player
4333 
4334     if ((kp = KeyPressedRange(&KEY_PRESSED(KEYSC_1), &KEY_PRESSED(KEYSC_9))) && CommPlayers > 1)
4335         {
4336         short save_myconnectindex;
4337 
4338         save_myconnectindex = myconnectindex;
4339 
4340         myconnectindex = (intptr_t)kp - (intptr_t)(&KEY_PRESSED(KEYSC_1));
4341 
4342         if (myconnectindex >= CommPlayers)
4343             myconnectindex = save_myconnectindex;
4344 
4345         screenpeek = myconnectindex;
4346 
4347         DoPlayerDivePalette(pp);
4348 
4349         // Now check for item or pain palette stuff
4350         // This sets the palette to whatever it is of the player you
4351         // just chose to view the game through.
4352 //      printf("SingPlayInput ALT+1-9 set_pal: pp->PlayerSprite = %d\n",pp->PlayerSprite);
4353         COVERsetbrightness(gs.Brightness,(char *)palette_data); // JBF: figure out what's going on here
4354 
4355         DoPlayerNightVisionPalette(pp);
4356 
4357         ResetKeyRange(&KEY_PRESSED(KEYSC_1), &KEY_PRESSED(KEYSC_9));
4358         }
4359 
4360     #if 0
4361     if (KEY_PRESSED(KEYSC_T))
4362         {
4363         KEY_PRESSED(KEYSC_T) = 0;
4364         PlayerTrackingMode ^= 1;
4365         }
4366     #endif
4367 
4368     if (KEY_PRESSED(KEYSC_H))
4369         {
4370         short pnum;
4371 
4372         KEY_PRESSED(KEYSC_H) = 0;
4373 
4374         TRAVERSE_CONNECT(pnum)
4375             {
4376             User[Player[pnum].PlayerSprite]->Health = 100;
4377             }
4378         }
4379     }
4380 
4381 VOID
DebugKeys(PLAYERp pp)4382 DebugKeys(PLAYERp pp)
4383     {
4384     short w, h;
4385 
4386     if (!(KEY_PRESSED(KEYSC_ALT) || KEY_PRESSED(KEYSC_RALT)))
4387         return;
4388 
4389     if (InputMode)
4390         return;
4391 
4392     if (CommEnabled)
4393         return;
4394 
4395     //
4396     // visiblity adjust
4397     //
4398 
4399     if (KEY_PRESSED(KEYSC_L) > 0)
4400         {
4401         if (KEY_PRESSED(KEYSC_LSHIFT) | KEY_PRESSED(KEYSC_RSHIFT))      // SHIFT
4402             {
4403             visibility = visibility - (visibility >> 3);
4404 
4405             if (visibility < 128)
4406                 visibility = 16348;
4407 
4408             //if (visibility > 16384)
4409             //    visibility = 128;
4410             }
4411         else
4412             {
4413             KEY_PRESSED(KEYSC_L) = 0;
4414 
4415             visibility = visibility - (visibility >> 3);
4416 
4417             if (visibility > 16384)
4418                 visibility = 128;
4419             }
4420         }
4421 
4422     //
4423     // parallax changes
4424     //
4425 
4426     if (KEY_PRESSED(KEYSC_X))
4427         {
4428         if (KEY_PRESSED(KEYSC_LSHIFT))
4429             {
4430             KEY_PRESSED(KEYSC_LSHIFT) = FALSE;
4431             KEY_PRESSED(KEYSC_X) = 0;
4432 
4433             parallaxyoffs += 10;
4434 
4435             if (parallaxyoffs > 100)
4436                 parallaxyoffs = 0;
4437             }
4438         else
4439             {
4440             KEY_PRESSED(KEYSC_X) = 0;
4441             parallaxtype++;
4442             if (parallaxtype > 2)
4443                 parallaxtype = 0;
4444             }
4445         }
4446     }
4447 
4448 #endif
4449 
4450 VOID
ConKey(void)4451 ConKey( void )
4452     {
4453     #if DEBUG
4454     // Console Input Panel
4455     if (!ConPanel && dimensionmode == 3)
4456         {
4457         //if (KEY_PRESSED(KEYSC_TILDE) && KEY_PRESSED(KEYSC_LSHIFT))
4458         if (KEY_PRESSED(KEYSC_TILDE))
4459             {
4460             KEY_PRESSED(KEYSC_TILDE) = FALSE;
4461             //KEY_PRESSED(KEYSC_LSHIFT) = FALSE;
4462             KB_FlushKeyboardQueue();
4463             ConPanel = TRUE;
4464             InputMode = TRUE;
4465             ConInputMode = TRUE;
4466             if (!CommEnabled)
4467                 GamePaused = TRUE;
4468             memset(MessageInputString, '\0', sizeof(MessageInputString));
4469             }
4470         }
4471     else
4472     if (ConPanel)
4473         {
4474         //if (KEY_PRESSED(KEYSC_TILDE) && KEY_PRESSED(KEYSC_LSHIFT))
4475         if (KEY_PRESSED(KEYSC_TILDE))
4476             {
4477             KEY_PRESSED(KEYSC_TILDE) = FALSE;
4478             //KEY_PRESSED(KEYSC_LSHIFT) = FALSE;
4479             KB_FlushKeyboardQueue();
4480             ConPanel = FALSE;
4481             ConInputMode = FALSE;
4482             InputMode = FALSE;
4483             if (!CommEnabled)
4484                 GamePaused = FALSE;
4485             memset(MessageInputString, '\0', sizeof(MessageInputString));
4486             SetFragBar(Player + myconnectindex);
4487             }
4488         }
4489     #endif
4490     }
4491 
4492 char WangBangMacro[10][64];
4493 
4494 VOID
FunctionKeys(PLAYERp pp)4495 FunctionKeys(PLAYERp pp)
4496     {
4497     extern BOOL GamePaused;
4498     extern short QuickLoadNum;
4499     static int rts_delay = 0;
4500     int fn_key = 0;
4501 
4502     rts_delay++;
4503 
4504     if (KEY_PRESSED(sc_F1))   { fn_key = 1; }
4505     if (KEY_PRESSED(sc_F2))   { fn_key = 2; }
4506     if (KEY_PRESSED(sc_F3))   { fn_key = 3; }
4507     if (KEY_PRESSED(sc_F4))   { fn_key = 4; }
4508     if (KEY_PRESSED(sc_F5))   { fn_key = 5; }
4509     if (KEY_PRESSED(sc_F6))   { fn_key = 6; }
4510     if (KEY_PRESSED(sc_F7))   { fn_key = 7; }
4511     if (KEY_PRESSED(sc_F8))   { fn_key = 8; }
4512     if (KEY_PRESSED(sc_F9))   { fn_key = 9; }
4513     if (KEY_PRESSED(sc_F10))  { fn_key = 10; }
4514 
4515     if (KEY_PRESSED(KEYSC_ALT) || KEY_PRESSED(KEYSC_RALT))
4516     {
4517         if (rts_delay > 16 && fn_key && CommEnabled && !gs.ParentalLock && !Global_PLock)
4518             {
4519             KEY_PRESSED(sc_F1 + fn_key - 1) = 0;
4520 
4521             rts_delay = 0;
4522 
4523             PlaySoundRTS(fn_key);
4524 
4525             if (CommEnabled)
4526                 {
4527                 short pnum;
4528                 PACKET_RTS p;
4529 
4530                 p.PacketType = PACKET_TYPE_RTS;
4531                 p.RTSnum = fn_key;
4532 
4533                 netbroadcastpacket((BYTEp)(&p), sizeof(p));            // TENSW
4534                 }
4535             }
4536 
4537         return;
4538         }
4539 
4540     if (KEY_PRESSED(KEYSC_LSHIFT) || KEY_PRESSED(KEYSC_RSHIFT))
4541         {
4542         if (fn_key && CommEnabled)
4543             {
4544             KEY_PRESSED(sc_F1 + fn_key - 1) = 0;
4545 
4546             if (CommEnabled)
4547                 {
4548                 short pnum;
4549 
4550                 sprintf(ds,"SENT: %s",WangBangMacro[fn_key-1]);
4551                 adduserquote(ds);
4552 
4553                 TRAVERSE_CONNECT(pnum)
4554                     {
4555                     if (pnum != myconnectindex)
4556                         {
4557                         sprintf(ds,"%s: %s",pp->PlayerName, WangBangMacro[fn_key-1]);
4558                         SendMessage(pnum, ds);
4559                         }
4560                     }
4561                 }
4562             }
4563 
4564         return;
4565         }
4566 
4567 
4568     if (CommPlayers <= 1)
4569         {
4570         // F2 save menu
4571         if (KEY_PRESSED(KEYSC_F2))
4572             {
4573             KEY_PRESSED(KEYSC_F2) = 0;
4574             if (!TEST(pp->Flags, PF_DEAD))
4575                 {
4576                 ForceMenus = TRUE;
4577                 ControlPanelType = ct_savemenu;
4578                 }
4579             }
4580 
4581         // F3 load menu
4582         if (KEY_PRESSED(KEYSC_F3))
4583             {
4584             KEY_PRESSED(KEYSC_F3) = 0;
4585             if (!TEST(pp->Flags, PF_DEAD))
4586                 {
4587                 ForceMenus = TRUE;
4588                 ControlPanelType = ct_loadmenu;
4589                 }
4590             }
4591 
4592         // F6 option menu
4593         if (KEY_PRESSED(KEYSC_F6))
4594             {
4595             extern BOOL QuickSaveMode;
4596             KEY_PRESSED(KEYSC_F6) = 0;
4597             if (!TEST(pp->Flags, PF_DEAD))
4598                 {
4599                 ForceMenus = TRUE;
4600                 ControlPanelType = ct_savemenu;
4601                 QuickSaveMode = TRUE;
4602                 }
4603             }
4604 
4605         // F9 quick load
4606         if (KEY_PRESSED(KEYSC_F9))
4607             {
4608             KEY_PRESSED(KEYSC_F9) = 0;
4609 
4610             if (!TEST(pp->Flags, PF_DEAD))
4611                 {
4612                 if (QuickLoadNum < 0)
4613                     {
4614                     PutStringInfoLine(pp, "Last saved game not found.");
4615                     }
4616                 else
4617                     {
4618                     KB_ClearKeysDown();
4619                     ForceMenus = TRUE;
4620                     ControlPanelType = ct_quickloadmenu;
4621                     }
4622                 }
4623             }
4624 
4625         }
4626 
4627 
4628     // F4 sound menu
4629     if (KEY_PRESSED(KEYSC_F4))
4630         {
4631         KEY_PRESSED(KEYSC_F4) = 0;
4632         ForceMenus = TRUE;
4633         ControlPanelType = ct_soundmenu;
4634         }
4635 
4636 
4637     // F7 VIEW control
4638     if (KEY_PRESSED(KEYSC_F7))
4639         {
4640         KEY_PRESSED(KEYSC_F7) = 0;
4641 
4642         if (KEY_PRESSED(KEYSC_LSHIFT) || KEY_PRESSED(KEYSC_RSHIFT))
4643             {
4644             if (TEST(pp->Flags, PF_VIEW_FROM_OUTSIDE))
4645                 pp->view_outside_dang = NORM_ANGLE(pp->view_outside_dang + 256);
4646             }
4647         else
4648             {
4649             if (TEST(pp->Flags, PF_VIEW_FROM_OUTSIDE))
4650                 {
4651                 RESET(pp->Flags, PF_VIEW_FROM_OUTSIDE);
4652                 }
4653             else
4654                 {
4655                 SET(pp->Flags, PF_VIEW_FROM_OUTSIDE);
4656                 pp->camera_dist = 0;
4657                 }
4658             }
4659         }
4660 
4661     // F8 toggle messages
4662     if (KEY_PRESSED(KEYSC_F8))
4663         {
4664         KEY_PRESSED(KEYSC_F8) = 0;
4665 
4666         gs.Messages ^= 1;
4667 
4668         if (gs.Messages)
4669             PutStringInfoLine(pp, "Messages ON");
4670         else
4671             PutStringInfoLine(pp, "Messages OFF");
4672         }
4673 
4674     // F10 quit menu
4675     if (KEY_PRESSED(KEYSC_F10))
4676         {
4677         KEY_PRESSED(KEYSC_F10) = 0;
4678         ForceMenus = TRUE;
4679         ControlPanelType = ct_quitmenu;
4680         }
4681 
4682     // F11 gamma correction
4683     if (KEY_PRESSED(KEYSC_F11) > 0)
4684         {
4685         KEY_PRESSED(KEYSC_F11) = 0;
4686 
4687         gs.Brightness++;
4688         if (gs.Brightness >= SLDR_BRIGHTNESSMAX)
4689             gs.Brightness = 0;
4690 
4691         sprintf(ds,"Brightness level (%d)",gs.Brightness+1);
4692         PutStringInfoLine(pp, ds);
4693 
4694         if(!pp->NightVision && pp->FadeAmt <= 0)
4695             {
4696             COVERsetbrightness(gs.Brightness,&palette_data[0][0]);
4697             }
4698 
4699         //DoPlayerDivePalette(pp);
4700         //DoPlayerNightVisionPalette(pp);
4701         }
4702 
4703     }
4704 
PauseKey(PLAYERp pp)4705 VOID PauseKey(PLAYERp pp)
4706     {
4707     extern BOOL GamePaused,CheatInputMode;
4708     extern short QuickLoadNum;
4709     extern BOOL enabled;
4710 
4711     if (KEY_PRESSED(sc_Pause) && !CommEnabled && !InputMode && !UsingMenus && !CheatInputMode && !ConPanel)
4712         {
4713         KEY_PRESSED(sc_Pause) = 0;
4714 
4715         PauseKeySet ^= 1;
4716 
4717         if (PauseKeySet)
4718             GamePaused = TRUE;
4719         else
4720             GamePaused = FALSE;
4721 
4722         if (GamePaused)
4723             {
4724             short w,h;
4725             #define MSG_GAME_PAUSED "Game Paused"
4726             MNU_MeasureString(MSG_GAME_PAUSED, &w, &h);
4727             PutStringTimer(pp, TEXT_TEST_COL(w), 100, MSG_GAME_PAUSED, 999);
4728             PauseSong(TRUE);
4729             }
4730         else
4731             {
4732             pClearTextLine(pp, 100);
4733             PauseSong(FALSE);
4734             }
4735         }
4736 
4737     if (!CommEnabled && TEST(pp->Flags, PF_DEAD))
4738         {
4739         if (ReloadPrompt)
4740             {
4741             if (QuickLoadNum < 0)
4742                 {
4743                 ReloadPrompt = FALSE;
4744                 }
4745             else
4746                 {
4747                 ForceMenus = TRUE;
4748                 ControlPanelType = ct_quickloadmenu;
4749                 }
4750             }
4751         }
4752     }
4753 
4754 
4755 
GetMessageInput(PLAYERp pp)4756 VOID GetMessageInput(PLAYERp pp)
4757     {
4758     int pnum = myconnectindex;
4759     short w,h;
4760     signed char MNU_InputSmallString(char *, short);
4761     signed char MNU_InputString(char *, short);
4762     static BOOL cur_show;
4763     static BOOL TeamSendAll, TeamSendTeam;
4764     #define TEAM_MENU "A - Send to ALL,  T - Send to TEAM"
4765     static char HoldMessageInputString[256];
4766     int i;
4767     BOOL IsCommand(char *str);
4768 
4769     if (!MessageInputMode && !ConInputMode)
4770         {
4771         if (BUTTON(gamefunc_SendMessage))
4772             {
4773             CONTROL_ClearButton(gamefunc_SendMessage);
4774             KB_FlushKeyboardQueue();
4775             MessageInputMode = TRUE;
4776             InputMode = TRUE;
4777             TeamSendTeam = FALSE;
4778             TeamSendAll = FALSE;
4779 
4780             if (MessageInputMode)
4781                 {
4782                 memset(MessageInputString, '\0', sizeof(MessageInputString));
4783                 }
4784             }
4785         }
4786     else
4787     if (MessageInputMode && !ConInputMode)
4788         {
4789         if (gs.BorderNum > BORDER_BAR+1)
4790             SetRedrawScreen(pp);
4791 
4792         // get input
4793         switch(MNU_InputSmallString(MessageInputString, 320-20))
4794             {
4795             case -1: // Cancel Input (pressed ESC) or Err
4796                 MessageInputMode = FALSE;
4797                 InputMode = FALSE;
4798                 KB_ClearKeysDown();
4799                 KB_FlushKeyboardQueue();
4800                 break;
4801             case FALSE: // Input finished (RETURN)
4802                 if (MessageInputString[0] == '\0')
4803                     {
4804                     // no input
4805                     MessageInputMode = FALSE;
4806                     InputMode = FALSE;
4807                     KB_ClearKeysDown();
4808                     KB_FlushKeyboardQueue();
4809                     CONTROL_ClearButton(gamefunc_Inventory);
4810                     }
4811                 else
4812                     {
4813                     if (gNet.TeamPlay)
4814                         {
4815                         if (memcmp(MessageInputString, TEAM_MENU, sizeof(TEAM_MENU)) != 0)
4816                             {
4817                             // see if its a command
4818                             if (IsCommand(MessageInputString))
4819                                 {
4820                                 TeamSendAll = TRUE;
4821                                 }
4822                             else
4823                                 {
4824                                 strcpy(HoldMessageInputString, MessageInputString);
4825                                 strcpy(MessageInputString, TEAM_MENU);
4826                                 break;
4827                                 }
4828                             }
4829                         else
4830                         if (memcmp(MessageInputString, TEAM_MENU, sizeof(TEAM_MENU)) == 0)
4831                             {
4832                             strcpy(MessageInputString, HoldMessageInputString);
4833                             TeamSendAll = TRUE;
4834                             }
4835                         }
4836 
4837                     SEND_MESSAGE:
4838 
4839                     // broadcast message
4840                     MessageInputMode = FALSE;
4841                     InputMode = FALSE;
4842                     KB_ClearKeysDown();
4843                     KB_FlushKeyboardQueue();
4844                     CONTROL_ClearButton(gamefunc_Inventory);
4845                     CON_ProcessUserCommand();     // Check to see if it's a cheat or command
4846 
4847                     for (i = 0; i < NUMGAMEFUNCTIONS; i++)
4848                         CONTROL_ClearButton(i);
4849 
4850                     // Put who sent this
4851                     sprintf(ds,"%s: %s",pp->PlayerName,MessageInputString);
4852 
4853                     if (gNet.TeamPlay)
4854                         {
4855                         TRAVERSE_CONNECT(pnum)
4856                             {
4857                             if (pnum != myconnectindex)
4858                                 {
4859                                 if (TeamSendAll)
4860                                     SendMessage(pnum, ds);
4861                                 else
4862                                 if (User[pp->PlayerSprite]->spal == User[Player[pnum].PlayerSprite]->spal)
4863                                     SendMessage(pnum, ds);
4864                                 }
4865                             }
4866                         }
4867                     else
4868                     TRAVERSE_CONNECT(pnum)
4869                         {
4870                         if (pnum != myconnectindex)
4871                             {
4872                             SendMessage(pnum, ds);
4873                             }
4874                         }
4875                      adduserquote(MessageInputString);
4876                      quotebot += 8;
4877                      quotebotgoal = quotebot;
4878                     }
4879                 break;
4880 
4881             case TRUE: // Got input
4882 
4883                 if (gNet.TeamPlay)
4884                     {
4885                     if (memcmp(MessageInputString, TEAM_MENU"a", sizeof(TEAM_MENU)+1) == 0)
4886                         {
4887                         strcpy(MessageInputString, HoldMessageInputString);
4888                         TeamSendAll = TRUE;
4889                         goto SEND_MESSAGE;
4890                         }
4891                     else
4892                     if (memcmp(MessageInputString, TEAM_MENU"t", sizeof(TEAM_MENU)+1) == 0)
4893                         {
4894                         strcpy(MessageInputString, HoldMessageInputString);
4895                         TeamSendTeam = TRUE;
4896                         goto SEND_MESSAGE;
4897                         }
4898                     else
4899                         {
4900                         // reset the string if anything else is typed
4901                         if (strlen(MessageInputString)+1 > sizeof(TEAM_MENU))
4902                             {
4903                             strcpy(MessageInputString, TEAM_MENU);
4904                             }
4905                         }
4906                     }
4907 
4908                 break;
4909             }
4910         }
4911     }
4912 
GetConInput(PLAYERp pp)4913 VOID GetConInput(PLAYERp pp)
4914     {
4915     int pnum = myconnectindex;
4916     short w,h;
4917     signed char MNU_InputSmallString(char *, short);
4918     signed char MNU_InputString(char *, short);
4919     static BOOL cur_show;
4920 
4921     if (MessageInputMode || HelpInputMode)
4922         return;
4923 
4924     ConKey();
4925 
4926     // Console input commands
4927     if (ConInputMode && !MessageInputMode)
4928         {
4929         // get input
4930         switch(MNU_InputSmallString(MessageInputString, 250))
4931             {
4932             case -1: // Cancel Input (pressed ESC) or Err
4933                 InputMode = FALSE;
4934                 KB_ClearKeysDown();
4935                 KB_FlushKeyboardQueue();
4936                 memset(MessageInputString, '\0', sizeof(MessageInputString));
4937                 break;
4938             case FALSE: // Input finished (RETURN)
4939                 if (MessageInputString[0] == '\0')
4940                     {
4941                     InputMode = FALSE;
4942                     KB_ClearKeysDown();
4943                     KB_FlushKeyboardQueue();
4944                     CONTROL_ClearButton(gamefunc_Inventory);
4945                     memset(MessageInputString, '\0', sizeof(MessageInputString));
4946                     }
4947                 else
4948                     {
4949                     InputMode = FALSE;
4950                     KB_ClearKeysDown();
4951                     KB_FlushKeyboardQueue();
4952                     CONTROL_ClearButton(gamefunc_Inventory);
4953                     CON_ConMessage("%s", MessageInputString);
4954                     CON_ProcessUserCommand();     // Check to see if it's a cheat or command
4955 
4956                     conbot += 6;
4957                     conbotgoal = conbot;
4958                     //addconquote(MessageInputString);
4959                     // Clear it out after every entry
4960                     memset(MessageInputString, '\0', sizeof(MessageInputString));
4961                     }
4962                 break;
4963             case TRUE: // Got input
4964                 break;
4965             }
4966         }
4967     }
4968 
4969 
GetHelpInput(PLAYERp pp)4970 VOID GetHelpInput(PLAYERp pp)
4971     {
4972     extern BOOL GamePaused;
4973 
4974     if (KEY_PRESSED(KEYSC_ALT) || KEY_PRESSED(KEYSC_RALT))
4975         return;
4976 
4977     if (KEY_PRESSED(KEYSC_LSHIFT) || KEY_PRESSED(KEYSC_RSHIFT))
4978         return;
4979 
4980     if (MessageInputMode || ConInputMode)
4981         return;
4982 
4983     // F1 help menu
4984     if (!HelpInputMode)
4985         {
4986         if (KEY_PRESSED(KEYSC_F1))
4987             {
4988             KEY_PRESSED(KEYSC_F1) = FALSE;
4989             HelpPage = 0;
4990             HelpInputMode = TRUE;
4991             PanelUpdateMode = FALSE;
4992             InputMode = TRUE;
4993             if (!CommEnabled)
4994                 GamePaused = TRUE;
4995             }
4996         }
4997     else
4998     if (HelpInputMode)
4999         {
5000         if (KEY_PRESSED(KEYSC_ESC))
5001             {
5002             KEY_PRESSED(KEYSC_ESC) = 0;
5003             KB_ClearKeysDown();
5004             PanelUpdateMode = TRUE;
5005             HelpInputMode = FALSE;
5006             InputMode = FALSE;
5007             if (!CommEnabled)
5008                 GamePaused = FALSE;
5009             SetRedrawScreen(pp);
5010             }
5011 
5012         if (KEY_PRESSED(KEYSC_SPACE) || KEY_PRESSED(KEYSC_ENTER) || KEY_PRESSED(KEYSC_PGDN) || KEY_PRESSED(KEYSC_DOWN) || KEY_PRESSED(KEYSC_RIGHT) || KEY_PRESSED(sc_kpad_3) || KEY_PRESSED(sc_kpad_2) || KEY_PRESSED(sc_kpad_6))
5013             {
5014             KEY_PRESSED(KEYSC_SPACE) = KEY_PRESSED(KEYSC_ENTER) = 0;
5015             KEY_PRESSED(KEYSC_PGDN) = 0;
5016             KEY_PRESSED(KEYSC_DOWN) = 0;
5017             KEY_PRESSED(KEYSC_RIGHT) = 0;
5018             KEY_PRESSED(sc_kpad_3) = 0;
5019             KEY_PRESSED(sc_kpad_2) = 0;
5020             KEY_PRESSED(sc_kpad_6) = 0;
5021 
5022             HelpPage++;
5023             if (HelpPage >= (int)SIZ(HelpPagePic))
5024                 // CTW MODIFICATION
5025                 // "Oops! I did it again..."
5026                 // HelpPage = SIZ(HelpPagePic) - 1;
5027                 HelpPage = 0;
5028                 // CTW MODIFICATION END
5029             }
5030 
5031         if (KEY_PRESSED(KEYSC_PGUP) || KEY_PRESSED(KEYSC_UP) || KEY_PRESSED(KEYSC_LEFT) || KEY_PRESSED(sc_kpad_9) || KEY_PRESSED(sc_kpad_8) || KEY_PRESSED(sc_kpad_4))
5032             {
5033             KEY_PRESSED(KEYSC_PGUP) = 0;
5034             KEY_PRESSED(KEYSC_UP) = 0;
5035             KEY_PRESSED(KEYSC_LEFT) = 0;
5036             KEY_PRESSED(sc_kpad_8) = 0;
5037             KEY_PRESSED(sc_kpad_9) = 0;
5038             KEY_PRESSED(sc_kpad_4) = 0;
5039 
5040             HelpPage--;
5041             if (HelpPage < 0)
5042                 // CTW MODIFICATION
5043                 // "Played with the logic, got lost in the game..."
5044                 HelpPage = SIZ(HelpPagePic) - 1;
5045                 // CTW MODIFICATION END
5046             }
5047         }
5048     }
5049 
5050 short MirrorDelay;
5051 int MouseYAxisMode = -1;
5052 
5053 VOID
getinput(SW_PACKET * loc)5054 getinput(SW_PACKET *loc)
5055     {
5056     BOOL found = FALSE;
5057     int i;
5058     PLAYERp pp = Player + myconnectindex;
5059     PLAYERp newpp = Player + myconnectindex;
5060     int pnum = myconnectindex;
5061     int inv_hotkey = 0;
5062 
5063 #define TURBOTURNTIME (120/8)
5064 #define NORMALTURN   (12+6)
5065 #define RUNTURN      (28)
5066 #define PREAMBLETURN 3
5067 #define NORMALKEYMOVE 35
5068 #define MAXVEL       ((NORMALKEYMOVE*2)+10)
5069 #define MAXSVEL      ((NORMALKEYMOVE*2)+10)
5070 #define MAXANGVEL    100
5071 #define SET_LOC_KEY(loc, sync_num, key_test) SET(loc, ((!!(key_test)) << (sync_num)))
5072 
5073     ControlInfo info;
5074     boolean running;
5075     int32 turnamount;
5076     static int32 turnheldtime;
5077     int32 keymove;
5078     int32 momx, momy;
5079     int aimvel;
5080     int mouseaxis;
5081 
5082     extern BOOL MenuButtonAutoRun;
5083     extern BOOL MenuButtonAutoAim;
5084 
5085     if (Prediction && CommEnabled)
5086         {
5087         newpp = ppp;
5088         }
5089 
5090     // reset all syncbits
5091     loc->bits = 0;
5092     svel = vel = angvel = aimvel = 0;
5093 
5094     // MAKE SURE THIS WILL GET SET
5095     SET_LOC_KEY(loc->bits, SK_QUIT_GAME, MultiPlayQuitFlag);
5096 
5097     if (gs.MouseAimingType == 1) // while held
5098         {
5099         if (BUTTON(gamefunc_Mouse_Aiming))
5100             {
5101             SET(pp->Flags, PF_MOUSE_AIMING_ON);
5102             gs.MouseAimingOn = TRUE;
5103             }
5104         else
5105             {
5106             if (TEST(pp->Flags, PF_MOUSE_AIMING_ON))
5107                 {
5108                 SET_LOC_KEY(loc->bits, SK_LOOK_UP, TRUE);
5109                 RESET(pp->Flags, PF_MOUSE_AIMING_ON);
5110                 gs.MouseAimingOn = FALSE;
5111                 }
5112             }
5113         }
5114     else
5115     if (gs.MouseAimingType == 0) // togglable button
5116         {
5117         if (BUTTON(gamefunc_Mouse_Aiming) && !BUTTONHELD(gamefunc_Mouse_Aiming))
5118             {
5119             FLIP(pp->Flags, PF_MOUSE_AIMING_ON);
5120             gs.MouseAimingOn = !gs.MouseAimingOn;
5121             if (!TEST(pp->Flags, PF_MOUSE_AIMING_ON))
5122                 {
5123                 SET_LOC_KEY(loc->bits, SK_LOOK_UP, TRUE);
5124                 PutStringInfo(pp, "Mouse Aiming Off");
5125                 }
5126             else
5127                 {
5128                 PutStringInfo(pp, "Mouse Aiming On");
5129                 }
5130             }
5131         }
5132 
5133     if (TEST(pp->Flags, PF_MOUSE_AIMING_ON))
5134         {
5135         mouseaxis = analog_lookingupanddown;
5136         }
5137     else
5138         {
5139         mouseaxis = MouseAnalogAxes[1];
5140         }
5141     if (mouseaxis != MouseYAxisMode)
5142         {
5143         CONTROL_MapAnalogAxis(1, mouseaxis, controldevice_mouse);
5144         MouseYAxisMode = mouseaxis;
5145         }
5146 
5147     CONTROL_GetInput(&info);
5148 
5149     info.dz = (info.dz * move_scale)>>8;
5150     info.dyaw = (info.dyaw * turn_scale)>>8;
5151 
5152     PauseKey(pp);
5153 
5154     if (PauseKeySet)
5155         return;
5156 
5157     if (!MenuInputMode && !UsingMenus)
5158         {
5159         GetMessageInput(pp);
5160         GetConInput(pp);
5161         GetHelpInput(pp);
5162         }
5163 
5164     // MAP KEY
5165     if (BUTTON(gamefunc_Map))
5166         {
5167         CONTROL_ClearButton(gamefunc_Map);
5168 
5169         // Init follow coords
5170         Follow_posx = pp->posx;
5171         Follow_posy = pp->posy;
5172 
5173         if (dimensionmode == 3)
5174             dimensionmode = 5;
5175         else
5176         if (dimensionmode == 5)
5177             dimensionmode = 6;
5178         else
5179             {
5180             MirrorDelay = 1;
5181             dimensionmode = 3;
5182             SetFragBar(pp);
5183             ScrollMode2D = FALSE;
5184             SetRedrawScreen(pp);
5185             }
5186         }
5187 
5188     // Toggle follow map mode on/off
5189     if (dimensionmode == 5 || dimensionmode == 6)
5190         {
5191         if (BUTTON(gamefunc_Map_Follow_Mode) && !BUTTONHELD(gamefunc_Map_Follow_Mode))
5192             {
5193             ScrollMode2D = !ScrollMode2D;
5194             Follow_posx = pp->posx;
5195             Follow_posy = pp->posy;
5196             }
5197         }
5198 
5199     // If in 2D follow mode, scroll around using glob vars
5200     // Tried calling this in domovethings, but key response it too poor, skips key presses
5201     // Note: ScrollMode2D = Follow mode, so this get called only during follow mode
5202     if (ScrollMode2D && pp == Player + myconnectindex && !Prediction)
5203         MoveScrollMode2D(Player + myconnectindex);
5204 
5205     // !JIM! Added UsingMenus so that you don't move at all while using menus
5206     if (MenuInputMode || UsingMenus || ScrollMode2D || InputMode)
5207         return;
5208 
5209     SET_LOC_KEY(loc->bits, SK_SPACE_BAR, ((!!KEY_PRESSED(KEYSC_SPACE)) | BUTTON(gamefunc_Open)));
5210 
5211     running = BUTTON(gamefunc_Run) || TEST(pp->Flags, PF_LOCK_RUN);
5212 
5213     if (BUTTON(gamefunc_Strafe) && !pp->sop)
5214         svel = -info.dyaw;
5215     else
5216         {
5217         if (info.dyaw > 0)
5218             angvel = labs((-info.dyaw));
5219         else
5220             angvel = info.dyaw;
5221         }
5222 
5223     aimvel = info.dpitch;
5224     aimvel = min(127, aimvel);
5225     aimvel = max(-128, aimvel);
5226     if (gs.MouseInvert)
5227         aimvel = -aimvel;
5228 
5229     svel -= info.dx;
5230     vel = -info.dz;
5231 
5232     if (running)
5233         {
5234         if (pp->sop_control)
5235             turnamount = RUNTURN * 3;
5236         else
5237             turnamount = RUNTURN;
5238 
5239         keymove = NORMALKEYMOVE << 1;
5240         }
5241     else
5242         {
5243         if (pp->sop_control)
5244             turnamount = NORMALTURN * 3;
5245         else
5246             turnamount = NORMALTURN;
5247 
5248         keymove = NORMALKEYMOVE;
5249         }
5250 
5251     if (BUTTON(gamefunc_Strafe) && !pp->sop)
5252         {
5253         if (BUTTON(gamefunc_Turn_Left))
5254             svel -= -keymove;
5255         if (BUTTON(gamefunc_Turn_Right))
5256             svel -= keymove;
5257         }
5258     else
5259         {
5260         if (BUTTON(gamefunc_Turn_Left))
5261             {
5262             turnheldtime += synctics;
5263             if (turnheldtime >= TURBOTURNTIME)
5264                 angvel -= turnamount;
5265             else
5266                 angvel -= PREAMBLETURN;
5267             }
5268         else
5269                 if (BUTTON(gamefunc_Turn_Right))
5270             {
5271             turnheldtime += synctics;
5272             if (turnheldtime >= TURBOTURNTIME)
5273                 angvel += turnamount;
5274             else
5275                 angvel += PREAMBLETURN;
5276             }
5277         else
5278             {
5279             turnheldtime = 0;
5280             }
5281         }
5282 
5283     if (BUTTON(gamefunc_Strafe_Left) && !pp->sop)
5284         svel += keymove;
5285 
5286     if (BUTTON(gamefunc_Strafe_Right) && !pp->sop)
5287         svel += -keymove;
5288 
5289     if (BUTTON(gamefunc_Move_Forward))
5290         {
5291         vel += keymove;
5292         //DSPRINTF(ds,"vel key %d",vel);
5293         //DebugWriteString(ds);
5294         }
5295     else
5296         {
5297         //DSPRINTF(ds,"vel %d",vel);
5298         //DebugWriteString(ds);
5299         }
5300 
5301     if (BUTTON(gamefunc_Move_Backward))
5302         vel += -keymove;
5303 
5304 
5305     if (vel < -MAXVEL)
5306         vel = -MAXVEL;
5307     if (vel > MAXVEL)
5308         vel = MAXVEL;
5309     if (svel < -MAXSVEL)
5310         svel = -MAXSVEL;
5311     if (svel > MAXSVEL)
5312         svel = MAXSVEL;
5313     if (angvel < -MAXANGVEL)
5314         angvel = -MAXANGVEL;
5315     if (angvel > MAXANGVEL)
5316         angvel = MAXANGVEL;
5317 
5318     momx = mulscale(vel, sintable[NORM_ANGLE(newpp->pang + 512)], 9);
5319     momy = mulscale(vel, sintable[NORM_ANGLE(newpp->pang)], 9);
5320 
5321     momx += mulscale(svel, sintable[NORM_ANGLE(newpp->pang)], 9);
5322     momy += mulscale(svel, sintable[NORM_ANGLE(newpp->pang + 1536)], 9);
5323 
5324     loc->vel = momx;
5325     loc->svel = momy;
5326     loc->angvel = angvel;
5327     loc->aimvel = aimvel;
5328 
5329     if (MenuButtonAutoRun)
5330         {
5331         MenuButtonAutoRun = FALSE;
5332         if ((!!TEST(pp->Flags, PF_LOCK_RUN)) != gs.AutoRun)
5333             SET_LOC_KEY(loc->bits, SK_RUN_LOCK, TRUE);
5334         }
5335 
5336     SET_LOC_KEY(loc->bits, SK_RUN_LOCK, BUTTON(gamefunc_AutoRun));
5337 
5338     if (!CommEnabled)
5339         {
5340         if (MenuButtonAutoAim)
5341             {
5342             MenuButtonAutoAim = FALSE;
5343             if ((!!TEST(pp->Flags, PF_AUTO_AIM)) != gs.AutoAim)
5344                 SET_LOC_KEY(loc->bits, SK_AUTO_AIM, TRUE);
5345             }
5346         }
5347     else
5348     if (KEY_PRESSED(sc_Pause))
5349         {
5350         SET_LOC_KEY(loc->bits, SK_PAUSE, KEY_PRESSED(sc_Pause));
5351         KEY_PRESSED(sc_Pause) = 0;
5352         }
5353 
5354     SET_LOC_KEY(loc->bits, SK_CENTER_VIEW, BUTTON(gamefunc_Center_View));
5355 
5356     SET_LOC_KEY(loc->bits, SK_RUN, BUTTON(gamefunc_Run));
5357     SET_LOC_KEY(loc->bits, SK_SHOOT, BUTTON(gamefunc_Fire));
5358 
5359     // actually snap
5360     SET_LOC_KEY(loc->bits, SK_SNAP_UP, BUTTON(gamefunc_Aim_Up));
5361     SET_LOC_KEY(loc->bits, SK_SNAP_DOWN, BUTTON(gamefunc_Aim_Down));
5362 
5363     // actually just look
5364     SET_LOC_KEY(loc->bits, SK_LOOK_UP, BUTTON(gamefunc_Look_Up));
5365     SET_LOC_KEY(loc->bits, SK_LOOK_DOWN, BUTTON(gamefunc_Look_Down));
5366 
5367 
5368     for (i = 0; i < MAX_WEAPONS_KEYS; i++)
5369         {
5370         if (BUTTON(gamefunc_Weapon_1 + i))
5371             {
5372             SET(loc->bits, i + 1);
5373             break;
5374             }
5375         }
5376 
5377     if (BUTTON(gamefunc_Next_Weapon))
5378         {
5379         USERp u = User[pp->PlayerSprite];
5380         short next_weapon = u->WeaponNum + 1;
5381         short start_weapon;
5382 
5383         CONTROL_ClearButton(gamefunc_Next_Weapon);
5384 
5385         start_weapon = u->WeaponNum + 1;
5386 
5387         if (u->WeaponNum == WPN_SWORD)
5388             start_weapon = WPN_STAR;
5389 
5390         if (u->WeaponNum == WPN_FIST)
5391             {
5392             next_weapon = 14;
5393             }
5394         else
5395             {
5396             next_weapon = -1;
5397             for (i = start_weapon; TRUE; i++)
5398                 {
5399                 if (i >= MAX_WEAPONS_KEYS)
5400                     {
5401                     next_weapon = 13;
5402                     break;
5403                     }
5404 
5405                 if (TEST(pp->WpnFlags, BIT(i)) && pp->WpnAmmo[i])
5406                     {
5407                     next_weapon = i;
5408                     break;
5409                     }
5410                 }
5411             }
5412 
5413         SET(loc->bits, next_weapon + 1);
5414         }
5415 
5416 
5417     if (BUTTON(gamefunc_Previous_Weapon))
5418         {
5419         USERp u = User[pp->PlayerSprite];
5420         short prev_weapon = u->WeaponNum - 1;
5421         short start_weapon;
5422 
5423         CONTROL_ClearButton(gamefunc_Previous_Weapon);
5424 
5425         start_weapon = u->WeaponNum - 1;
5426 
5427         if (u->WeaponNum == WPN_SWORD)
5428             {
5429             prev_weapon = 13;
5430             }
5431         else
5432         if (u->WeaponNum == WPN_STAR)
5433             {
5434             prev_weapon = 14;
5435             }
5436         else
5437             {
5438             prev_weapon = -1;
5439             for (i = start_weapon; TRUE; i--)
5440                 {
5441                 if (i <= -1)
5442                     i = WPN_HEART;
5443 
5444                 if (TEST(pp->WpnFlags, BIT(i)) && pp->WpnAmmo[i])
5445                     {
5446                     prev_weapon = i;
5447                     break;
5448                     }
5449                 }
5450             }
5451 
5452         SET(loc->bits, prev_weapon + 1);
5453         }
5454 
5455     inv_hotkey = 0;
5456     if (BUTTON(gamefunc_Med_Kit))
5457         inv_hotkey = INVENTORY_MEDKIT+1;
5458     if (BUTTON(gamefunc_Smoke_Bomb))
5459         inv_hotkey = INVENTORY_CLOAK+1;
5460     if (BUTTON(gamefunc_Night_Vision))
5461         inv_hotkey = INVENTORY_NIGHT_VISION+1;
5462     if (BUTTON(gamefunc_Gas_Bomb))
5463         inv_hotkey = INVENTORY_CHEMBOMB+1;
5464     if (BUTTON(gamefunc_Flash_Bomb) && dimensionmode == 3)
5465         inv_hotkey = INVENTORY_FLASHBOMB+1;
5466     if (BUTTON(gamefunc_Caltrops))
5467         inv_hotkey = INVENTORY_CALTROPS+1;
5468 
5469     SET(loc->bits, inv_hotkey<<SK_INV_HOTKEY_BIT0);
5470 
5471     SET_LOC_KEY(loc->bits, SK_INV_USE, BUTTON(gamefunc_Inventory));
5472 
5473     SET_LOC_KEY(loc->bits, SK_OPERATE, BUTTON(gamefunc_Open));
5474     SET_LOC_KEY(loc->bits, SK_JUMP, BUTTON(gamefunc_Jump));
5475     SET_LOC_KEY(loc->bits, SK_CRAWL, BUTTON(gamefunc_Crouch));
5476 
5477     SET_LOC_KEY(loc->bits, SK_TURN_180, BUTTON(gamefunc_TurnAround));
5478 
5479     SET_LOC_KEY(loc->bits, SK_INV_LEFT, BUTTON(gamefunc_Inventory_Left));
5480     SET_LOC_KEY(loc->bits, SK_INV_RIGHT, BUTTON(gamefunc_Inventory_Right));
5481 
5482     SET_LOC_KEY(loc->bits, SK_HIDE_WEAPON, BUTTON(gamefunc_Holster_Weapon));
5483 
5484     // need BUTTON
5485     SET_LOC_KEY(loc->bits, SK_CRAWL_LOCK, KEY_PRESSED(KEYSC_NUM));
5486 
5487     if (gNet.MultiGameType == MULTI_GAME_COOPERATIVE)
5488         {
5489         if (BUTTON(gamefunc_See_Co_Op_View))
5490             {
5491             CONTROL_ClearButton(gamefunc_See_Co_Op_View);
5492             NextScreenPeek();
5493 
5494             if (dimensionmode != 2 && screenpeek == myconnectindex)
5495                 {
5496             // JBF: figure out what's going on here
5497                 COVERsetbrightness(gs.Brightness,&palette_data[0][0]);
5498                 memcpy(pp->temp_pal, palette_data, sizeof(palette_data));
5499                 DoPlayerDivePalette(pp);  // Check Dive again
5500                 DoPlayerNightVisionPalette(pp);  // Check Night Vision again
5501                 } else
5502                 {
5503                 PLAYERp tp = Player+screenpeek;
5504 
5505                 if (tp->FadeAmt<=0)
5506                     memcpy(pp->temp_pal, palette_data, sizeof(palette_data));
5507                 else
5508                     memcpy(pp->temp_pal, tp->temp_pal, sizeof(tp->temp_pal));
5509                 COVERsetbrightness(gs.Brightness,&palette_data[0][0]);
5510                 DoPlayerDivePalette(tp);
5511                 DoPlayerNightVisionPalette(tp);
5512                 }
5513             }
5514         }
5515 
5516 #if DEBUG
5517     DebugKeys(pp);
5518 
5519     if (!CommEnabled)                   // Single player only keys
5520         SinglePlayInput(pp);
5521 #endif
5522 
5523     FunctionKeys(pp);
5524 
5525     if (BUTTON(gamefunc_Toggle_Crosshair))
5526         {
5527         CONTROL_ClearButton(gamefunc_Toggle_Crosshair);
5528         pToggleCrosshair(pp);
5529         }
5530     }
5531 
5532 #define MAP_WHITE_SECTOR    (LT_GREY + 2)
5533 #define MAP_RED_SECTOR      (RED + 6)
5534 #define MAP_FLOOR_SPRITE    (RED + 8)
5535 #define MAP_ENEMY           (RED + 10)
5536 #define MAP_SPRITE          (FIRE + 8)
5537 #define MAP_PLAYER          (GREEN + 6)
5538 
5539 #define MAP_BLOCK_SPRITE    (DK_BLUE + 6)
5540 
drawoverheadmap(int cposx,int cposy,int czoom,short cang)5541 void drawoverheadmap(int cposx, int cposy, int czoom, short cang)
5542     {
5543     int i, j, k, l, x1, y1, x2, y2, x3, y3, x4, y4, ox, oy, xoff, yoff;
5544     int dax, day, cosang, sinang, xspan, yspan, sprx, spry;
5545     int xrepeat, yrepeat, z1, z2, startwall, endwall, tilenum, daang;
5546     int xvect, yvect, xvect2, yvect2;
5547     char col;
5548     walltype *wal, *wal2;
5549     spritetype *spr;
5550     short p;
5551     static int pspr_ndx[8]={0,0,0,0,0,0,0,0};
5552     BOOL sprisplayer = FALSE;
5553     short txt_x, txt_y;
5554 
5555     // draw location text
5556     if (gs.BorderNum <= BORDER_BAR-1)
5557         {
5558         txt_x = 7;
5559         txt_y = 168;
5560         } else
5561         {
5562         txt_x = 7;
5563         txt_y = 147;
5564         }
5565 
5566     if (ScrollMode2D)
5567         {
5568         minigametext(txt_x,txt_y-7,"Follow Mode",0,2+8);
5569         }
5570 
5571     if (UserMapName[0])
5572         sprintf(ds,"%s",UserMapName);
5573     else
5574         sprintf(ds,"%s",LevelInfo[Level].Description);
5575 
5576     minigametext(txt_x,txt_y,ds,0,2+8);
5577 
5578     //////////////////////////////////
5579 
5580     xvect = sintable[(2048 - cang) & 2047] * czoom;
5581     yvect = sintable[(1536 - cang) & 2047] * czoom;
5582     xvect2 = mulscale(xvect, yxaspect, 16);
5583     yvect2 = mulscale(yvect, yxaspect, 16);
5584 
5585     // Draw red lines
5586     for (i = 0; i < numsectors; i++)
5587         {
5588         startwall = sector[i].wallptr;
5589         endwall = sector[i].wallptr + sector[i].wallnum - 1;
5590 
5591         z1 = sector[i].ceilingz;
5592         z2 = sector[i].floorz;
5593 
5594         for (j = startwall, wal = &wall[startwall]; j <= endwall; j++, wal++)
5595             {
5596             k = wal->nextwall;
5597             if (k < 0)
5598                 continue;
5599 
5600             if ((show2dwall[j >> 3] & (1 << (j & 7))) == 0)
5601                 continue;
5602             if ((k > j) && ((show2dwall[k >> 3] & (1 << (k & 7))) > 0))
5603                 continue;
5604 
5605             if (sector[wal->nextsector].ceilingz == z1)
5606                 if (sector[wal->nextsector].floorz == z2)
5607                     if (((wal->cstat | wall[wal->nextwall].cstat) & (16 + 32)) == 0)
5608                         continue;
5609 
5610             col = 152;
5611 
5612             //if (dimensionmode == 2)
5613             if (dimensionmode == 6)
5614                 {
5615                 if (sector[i].floorz != sector[i].ceilingz)
5616                     if (sector[wal->nextsector].floorz != sector[wal->nextsector].ceilingz)
5617                         if (((wal->cstat | wall[wal->nextwall].cstat) & (16 + 32)) == 0)
5618                             if (sector[i].floorz == sector[wal->nextsector].floorz)
5619                                 continue;
5620                 if (sector[i].floorpicnum != sector[wal->nextsector].floorpicnum)
5621                     continue;
5622                 if (sector[i].floorshade != sector[wal->nextsector].floorshade)
5623                     continue;
5624                 col = 12;
5625                 }
5626 
5627             ox = wal->x - cposx;
5628             oy = wal->y - cposy;
5629             x1 = mulscale(ox, xvect, 16) - mulscale(oy, yvect, 16);
5630             y1 = mulscale(oy, xvect2, 16) + mulscale(ox, yvect2, 16);
5631 
5632             wal2 = &wall[wal->point2];
5633             ox = wal2->x - cposx;
5634             oy = wal2->y - cposy;
5635             x2 = mulscale(ox, xvect, 16) - mulscale(oy, yvect, 16);
5636             y2 = mulscale(oy, xvect2, 16) + mulscale(ox, yvect2, 16);
5637 
5638             drawline256(x1 + (xdim << 11), y1 + (ydim << 11), x2 + (xdim << 11), y2 + (ydim << 11), col);
5639             }
5640         }
5641 
5642     // Draw sprites
5643     k = Player[screenpeek].PlayerSprite;
5644     for (i = 0; i < numsectors; i++)
5645         for (j = headspritesect[i]; j >= 0; j = nextspritesect[j])
5646         {
5647             TRAVERSE_CONNECT(p)
5648                 {
5649                 if(Player[p].PlayerSprite == j)
5650                     {
5651                     if(sprite[Player[p].PlayerSprite].xvel > 16)
5652                         pspr_ndx[myconnectindex] = ((totalclock>>4)&3);
5653                     sprisplayer = TRUE;
5654 
5655                     goto SHOWSPRITE;
5656                     }
5657                 }
5658             if ((show2dsprite[j >> 3] & (1 << (j & 7))) > 0)
5659                 {
5660                 SHOWSPRITE:
5661                 spr = &sprite[j];
5662 
5663                 col = 56;
5664                 if ((spr->cstat & 1) > 0)
5665                     col = 248;
5666                 if (j == k)
5667                     col = 31;
5668 
5669                 sprx = spr->x;
5670                 spry = spr->y;
5671 
5672                 k = spr->statnum;
5673                 if ((k >= 1) && (k <= 8) && (k != 2))   // Interpolate moving
5674                     {
5675                     sprx = sprite[j].x;
5676                     spry = sprite[j].y;
5677                     }
5678 
5679                 switch (spr->cstat & 48)
5680                     {
5681                 case 0:  // Regular sprite
5682                     if(Player[p].PlayerSprite == j)
5683                     {
5684                     ox = sprx - cposx;
5685                     oy = spry - cposy;
5686                     x1 = mulscale(ox, xvect, 16) - mulscale(oy, yvect, 16);
5687                     y1 = mulscale(oy, xvect2, 16) + mulscale(ox, yvect2, 16);
5688 
5689                     if (dimensionmode == 5 && (gNet.MultiGameType != MULTI_GAME_COMMBAT || j == Player[screenpeek].PlayerSprite))
5690                         {
5691                         ox = (sintable[(spr->ang + 512) & 2047] >> 7);
5692                         oy = (sintable[(spr->ang) & 2047] >> 7);
5693                         x2 = mulscale(ox, xvect, 16) - mulscale(oy, yvect, 16);
5694                         y2 = mulscale(oy, xvect, 16) + mulscale(ox, yvect, 16);
5695 
5696                         if (j == Player[screenpeek].PlayerSprite)
5697                             {
5698                             x2 = 0L;
5699                             y2 = -(czoom << 5);
5700                             }
5701 
5702                         x3 = mulscale(x2, yxaspect, 16);
5703                         y3 = mulscale(y2, yxaspect, 16);
5704 
5705                         drawline256(x1 - x2 + (xdim << 11), y1 - y3 + (ydim << 11),
5706                             x1 + x2 + (xdim << 11), y1 + y3 + (ydim << 11), col);
5707                         drawline256(x1 - y2 + (xdim << 11), y1 + x3 + (ydim << 11),
5708                             x1 + x2 + (xdim << 11), y1 + y3 + (ydim << 11), col);
5709                         drawline256(x1 + y2 + (xdim << 11), y1 - x3 + (ydim << 11),
5710                             x1 + x2 + (xdim << 11), y1 + y3 + (ydim << 11), col);
5711                         }
5712                     else
5713                         {
5714                         if (((gotsector[i >> 3] & (1 << (i & 7))) > 0) && (czoom > 192))
5715                             {
5716                             daang = (spr->ang - cang) & 2047;
5717                             if (j == Player[screenpeek].PlayerSprite)
5718                                 {
5719                                 x1 = 0;
5720                                 //y1 = (yxaspect << 2);
5721                                 y1 = 0;
5722                                 daang = 0;
5723                                 }
5724 
5725                             // Special case tiles
5726                             if (spr->picnum == 3123) break;
5727 
5728                             if(sprisplayer)
5729                                 {
5730                                 if (gNet.MultiGameType != MULTI_GAME_COMMBAT || j == Player[screenpeek].PlayerSprite)
5731                                     rotatesprite((x1 << 4) + (xdim << 15), (y1 << 4) + (ydim << 15), mulscale(czoom * (spr->yrepeat), yxaspect, 16), daang, 1196+pspr_ndx[myconnectindex], spr->shade, spr->pal, (spr->cstat & 2) >> 1, windowx1, windowy1, windowx2, windowy2);
5732                                 }
5733                             else
5734                                 rotatesprite((x1 << 4) + (xdim << 15), (y1 << 4) + (ydim << 15), mulscale(czoom * (spr->yrepeat), yxaspect, 16), daang, spr->picnum, spr->shade, spr->pal, (spr->cstat & 2) >> 1, windowx1, windowy1, windowx2, windowy2);
5735                             }
5736                         }
5737                     }
5738                     break;
5739                 case 16: // Rotated sprite
5740                     x1 = sprx;
5741                     y1 = spry;
5742                     tilenum = spr->picnum;
5743                     xoff = (int) ((signed char) ((picanm[tilenum] >> 8) & 255)) + ((int) spr->xoffset);
5744                     if ((spr->cstat & 4) > 0)
5745                         xoff = -xoff;
5746                     k = spr->ang;
5747                     l = spr->xrepeat;
5748                     dax = sintable[k & 2047] * l;
5749                     day = sintable[(k + 1536) & 2047] * l;
5750                     l = tilesizx[tilenum];
5751                     k = (l >> 1) + xoff;
5752                     x1 -= mulscale(dax, k, 16);
5753                     x2 = x1 + mulscale(dax, l, 16);
5754                     y1 -= mulscale(day, k, 16);
5755                     y2 = y1 + mulscale(day, l, 16);
5756 
5757                     ox = x1 - cposx;
5758                     oy = y1 - cposy;
5759                     x1 = mulscale(ox, xvect, 16) - mulscale(oy, yvect, 16);
5760                     y1 = mulscale(oy, xvect2, 16) + mulscale(ox, yvect2, 16);
5761 
5762                     ox = x2 - cposx;
5763                     oy = y2 - cposy;
5764                     x2 = mulscale(ox, xvect, 16) - mulscale(oy, yvect, 16);
5765                     y2 = mulscale(oy, xvect2, 16) + mulscale(ox, yvect2, 16);
5766 
5767                     drawline256(x1 + (xdim << 11), y1 + (ydim << 11),
5768                         x2 + (xdim << 11), y2 + (ydim << 11), col);
5769 
5770                     break;
5771                 case 32:    // Floor sprite
5772                     if (dimensionmode == 5)
5773                         {
5774                         tilenum = spr->picnum;
5775                         xoff = (int) ((signed char) ((picanm[tilenum] >> 8) & 255)) + ((int) spr->xoffset);
5776                         yoff = (int) ((signed char) ((picanm[tilenum] >> 16) & 255)) + ((int) spr->yoffset);
5777                         if ((spr->cstat & 4) > 0)
5778                             xoff = -xoff;
5779                         if ((spr->cstat & 8) > 0)
5780                             yoff = -yoff;
5781 
5782                         k = spr->ang;
5783                         cosang = sintable[(k + 512) & 2047];
5784                         sinang = sintable[k];
5785                         xspan = tilesizx[tilenum];
5786                         xrepeat = spr->xrepeat;
5787                         yspan = tilesizy[tilenum];
5788                         yrepeat = spr->yrepeat;
5789 
5790                         dax = ((xspan >> 1) + xoff) * xrepeat;
5791                         day = ((yspan >> 1) + yoff) * yrepeat;
5792                         x1 = sprx + mulscale(sinang, dax, 16) + mulscale(cosang, day, 16);
5793                         y1 = spry + mulscale(sinang, day, 16) - mulscale(cosang, dax, 16);
5794                         l = xspan * xrepeat;
5795                         x2 = x1 - mulscale(sinang, l, 16);
5796                         y2 = y1 + mulscale(cosang, l, 16);
5797                         l = yspan * yrepeat;
5798                         k = -mulscale(cosang, l, 16);
5799                         x3 = x2 + k;
5800                         x4 = x1 + k;
5801                         k = -mulscale(sinang, l, 16);
5802                         y3 = y2 + k;
5803                         y4 = y1 + k;
5804 
5805                         ox = x1 - cposx;
5806                         oy = y1 - cposy;
5807                         x1 = mulscale(ox, xvect, 16) - mulscale(oy, yvect, 16);
5808                         y1 = mulscale(oy, xvect2, 16) + mulscale(ox, yvect2, 16);
5809 
5810                         ox = x2 - cposx;
5811                         oy = y2 - cposy;
5812                         x2 = mulscale(ox, xvect, 16) - mulscale(oy, yvect, 16);
5813                         y2 = mulscale(oy, xvect2, 16) + mulscale(ox, yvect2, 16);
5814 
5815                         ox = x3 - cposx;
5816                         oy = y3 - cposy;
5817                         x3 = mulscale(ox, xvect, 16) - mulscale(oy, yvect, 16);
5818                         y3 = mulscale(oy, xvect2, 16) + mulscale(ox, yvect2, 16);
5819 
5820                         ox = x4 - cposx;
5821                         oy = y4 - cposy;
5822                         x4 = mulscale(ox, xvect, 16) - mulscale(oy, yvect, 16);
5823                         y4 = mulscale(oy, xvect2, 16) + mulscale(ox, yvect2, 16);
5824 
5825                         drawline256(x1 + (xdim << 11), y1 + (ydim << 11),
5826                             x2 + (xdim << 11), y2 + (ydim << 11), col);
5827 
5828                         drawline256(x2 + (xdim << 11), y2 + (ydim << 11),
5829                             x3 + (xdim << 11), y3 + (ydim << 11), col);
5830 
5831                         drawline256(x3 + (xdim << 11), y3 + (ydim << 11),
5832                             x4 + (xdim << 11), y4 + (ydim << 11), col);
5833 
5834                         drawline256(x4 + (xdim << 11), y4 + (ydim << 11),
5835                             x1 + (xdim << 11), y1 + (ydim << 11), col);
5836 
5837                         }
5838                     break;
5839                     }
5840                 }
5841         }
5842     // Draw white lines
5843     for (i = 0; i < numsectors; i++)
5844         {
5845         startwall = sector[i].wallptr;
5846         endwall = sector[i].wallptr + sector[i].wallnum - 1;
5847 
5848         for (j = startwall, wal = &wall[startwall]; j <= endwall; j++, wal++)
5849             {
5850             if (wal->nextwall >= 0)
5851                 continue;
5852 
5853             if ((show2dwall[j >> 3] & (1 << (j & 7))) == 0)
5854                 continue;
5855 
5856             if (tilesizx[wal->picnum] == 0)
5857                 continue;
5858             if (tilesizy[wal->picnum] == 0)
5859                 continue;
5860 
5861             ox = wal->x - cposx;
5862             oy = wal->y - cposy;
5863             x1 = mulscale(ox, xvect, 16) - mulscale(oy, yvect, 16);
5864             y1 = mulscale(oy, xvect2, 16) + mulscale(ox, yvect2, 16);
5865 
5866             wal2 = &wall[wal->point2];
5867             ox = wal2->x - cposx;
5868             oy = wal2->y - cposy;
5869             x2 = mulscale(ox, xvect, 16) - mulscale(oy, yvect, 16);
5870             y2 = mulscale(oy, xvect2, 16) + mulscale(ox, yvect2, 16);
5871 
5872             drawline256(x1 + (xdim << 11), y1 + (ydim << 11), x2 + (xdim << 11), y2 + (ydim << 11), 24);
5873             }
5874         }
5875 
5876     }
5877 
5878 extern int tilefileoffs[MAXTILES];//offset into the
5879 extern char tilefilenum[MAXTILES];//0-11
5880 
5881 #if 0
5882 loadtile (short tilenume)
5883 {
5884     char *ptr;
5885         int i;
5886         char zerochar = 0;
5887 
5888         if (walsiz[tilenume] <= 0)
5889            return;
5890 
5891     i = tilefilenum[tilenume];
5892     if (i != artfilnum)
5893             {
5894         if (artfil != -1)
5895                     kclose(artfil);
5896         artfilnum = i;
5897         artfilplc = 0L;
5898 
5899         artfilename[7] = (i%10)+48;
5900         artfilename[6] = ((i/10)%10)+48;
5901         artfilename[5] = ((i/100)%10)+48;
5902         artfil = kopen4load(artfilename);
5903         faketimerhandler();
5904             }
5905 
5906     if (waloff[tilenume] == 0)
5907             allocache(&waloff[tilenume],walsiz[tilenume],&zerochar);
5908 
5909     if (artfilplc != tilefileoffs[tilenume])
5910     {
5911         klseek(artfil,tilefileoffs[tilenume]-artfilplc,SEEK_CUR);
5912         faketimerhandler();
5913     }
5914 
5915     ptr = (char *)waloff[tilenume];
5916     kread(artfil,ptr,walsiz[tilenume]);
5917     faketimerhandler();
5918     artfilplc = tilefileoffs[tilenume]+walsiz[tilenume];
5919 }
5920 #endif
5921 
5922 #if RANDOM_DEBUG
5923 int
RandomRange(int range,char * file,unsigned line)5924 RandomRange(int range, char *file, unsigned line)
5925     {
5926     ULONG rand_num;
5927     ULONG value;
5928     extern FILE * fout_err;
5929     extern ULONG MoveThingsCount;
5930 
5931     if (RandomPrint && !Prediction)
5932         {
5933         sprintf(ds,"mtc %d, %s, line %d, %d",MoveThingsCount,file,line,randomseed);
5934         DebugWriteString(ds);
5935         }
5936 
5937     if (range <= 0)
5938         return(0);
5939 
5940     rand_num = krand2();
5941 
5942     if (rand_num == 65535U)
5943         rand_num--;
5944 
5945     // shift values to give more precision
5946     value = (rand_num << 14) / ((65535UL << 14) / range);
5947 
5948     if (value >= range)
5949         value = range - 1;
5950 
5951     return(value);
5952     }
5953 #else
5954 int
RandomRange(int range)5955 RandomRange(int range)
5956     {
5957     ULONG rand_num;
5958     ULONG value;
5959 
5960     if (range <= 0)
5961         return(0);
5962 
5963     rand_num = RANDOM();
5964 
5965     if (rand_num == 65535U)
5966         rand_num--;
5967 
5968     // shift values to give more precision
5969     value = (rand_num << 14) / ((65535UL << 14) / range);
5970 
5971     if (value >= (ULONG)range)
5972         value = range - 1;
5973 
5974     return(value);
5975     }
5976 #endif
5977 
5978 int
StdRandomRange(int range)5979 StdRandomRange(int range)
5980     {
5981     ULONG rand_num;
5982     ULONG value;
5983 
5984     if (range <= 0)
5985         return(0);
5986 
5987     rand_num = STD_RANDOM();
5988 
5989     if (rand_num == RAND_MAX)
5990         rand_num--;
5991 
5992     // shift values to give more precision
5993 #if (RAND_MAX > 0x7fff)
5994     value = rand_num / (((int)RAND_MAX) / range);
5995 #else
5996     value = (rand_num << 14) / ((((int)RAND_MAX) << 14) / range);
5997 #endif
5998 
5999     if (value >= (ULONG)range)
6000         value = range - 1;
6001 
6002     return(value);
6003     }
6004 
6005 void
NextScreenPeek(void)6006 NextScreenPeek(void)
6007     {
6008     int startpeek = screenpeek;
6009     do
6010         {
6011         screenpeek = connectpoint2[screenpeek];
6012         if (screenpeek < 0)
6013             screenpeek = connecthead;
6014         if (!Player[screenpeek].IsDisconnected)
6015             {
6016             CON_Message("Viewing %s", Player[screenpeek].PlayerName);
6017             break;
6018             }
6019         }
6020     while (screenpeek != startpeek);
6021     }
6022 
6023 static int
osdcmd_restartvid(const osdfuncparm_t * parm)6024 osdcmd_restartvid(const osdfuncparm_t *parm)
6025     {
6026     extern BOOL RestartVideo;
6027     extern VMODE NewVideoMode;
6028 
6029     RestartVideo = TRUE;
6030     NewVideoMode.x = xdim;
6031     NewVideoMode.y = ydim;
6032     NewVideoMode.bpp = bpp;
6033     NewVideoMode.fs = fullscreen;
6034 
6035     return OSDCMD_OK;
6036     }
6037 
6038 static int
osdcmd_vidmode(const osdfuncparm_t * parm)6039 osdcmd_vidmode(const osdfuncparm_t *parm)
6040     {
6041     extern BOOL RestartVideo;
6042     extern VMODE NewVideoMode;
6043 
6044     int newx = xdim, newy = ydim, newbpp = bpp, newfullscreen = fullscreen;
6045 
6046     if (parm->numparms < 1 || parm->numparms > 4) return OSDCMD_SHOWHELP;
6047 
6048     switch (parm->numparms)
6049         {
6050         case 1:   // bpp switch
6051             newbpp = Batol(parm->parms[0]);
6052             break;
6053         case 2: // res switch
6054             newx = Batol(parm->parms[0]);
6055             newy = Batol(parm->parms[1]);
6056             break;
6057         case 3:   // res & bpp switch
6058         case 4:
6059             newx = Batol(parm->parms[0]);
6060             newy = Batol(parm->parms[1]);
6061             newbpp = Batol(parm->parms[2]);
6062             if (parm->numparms == 4)
6063                 newfullscreen = (Batol(parm->parms[3]) != 0);
6064             break;
6065         }
6066 
6067     if (checkvideomode(&newx, &newy, newbpp, newfullscreen, 0) >= 0)
6068         {
6069         RestartVideo = TRUE;
6070         NewVideoMode.x = newx;
6071         NewVideoMode.y = newy;
6072         NewVideoMode.bpp = newbpp;
6073         NewVideoMode.fs = newfullscreen;
6074         }
6075 
6076     return OSDCMD_OK;
6077     }
6078 
6079 #include "saveable.h"
6080 
6081 static saveable_data saveable_build_data[] = {
6082     SAVE_DATA(sector),
6083     SAVE_DATA(sprite),
6084     SAVE_DATA(wall)
6085 };
6086 
6087 saveable_module saveable_build = {
6088     // code
6089     NULL,
6090     0,
6091 
6092     // data
6093     saveable_build_data,
6094     NUM_SAVEABLE_ITEMS(saveable_build_data)
6095 };
6096 
6097 // vim:ts=4:sw=4:expandtab:
6098