blob: b0f4442d329a4c26a0d967c9f094f14cbb1e8554 [file] [log] [blame]
Franklin Weia855d622017-01-21 15:18:31 -05001//-------------------------------------------------------------------------
2/*
3Copyright (C) 1996, 2003 - 3D Realms Entertainment
4
5This file is part of Duke Nukem 3D version 1.5 - Atomic Edition
6
7Duke Nukem 3D is free software; you can redistribute it and/or
8modify it under the terms of the GNU General Public License
9as published by the Free Software Foundation; either version 2
10of the License, or (at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
16See the GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19aint32_t with this program; if not, write to the Free Software
20Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22Original Source: 1996 - Todd Replogle
23Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
24*/
25//-------------------------------------------------------------------------
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <stdarg.h>
31#include <errno.h>
32#include "global.h"
33#include "duke3d.h"
34
Franklin Weia855d622017-01-21 15:18:31 -050035char *mymembuf;
36uint8_t MusicPtr[72000];
37
38
39crc32_t crc32lookup[] = {
40 // good:
41 { CRC_BASE_GRP_SHAREWARE_13, "SHAREWARE 1.3D", 11035779 },
42 { CRC_BASE_GRP_FULL_13, "FULL 1.3D ", 26524524 },
43 { CRC_BASE_GRP_PLUTONIUM_14, "PLUTONIUM 1.4 ", 44348015 },
44 { CRC_BASE_GRP_ATOMIC_15, "ATOMIC 1.5 ", 44356548 },
45 // unknown:
46 { 0, "HACK/UNKNOWN ", 0}
47 };
48
49uint8_t conVersion = 13;
50uint8_t grpVersion = 0;
51
52// FIX_00015: Backward compliance with older demos (down to demos v27, 28, 116 and 117 only)
53
54// For BYTEVERSION diff, 27/116 vs 28/117 see extras\duke3d.h vs source\duke3d.h
55// from the official source code release.
56
57int BYTEVERSION_27 = 27; // 1.3 under 1.4 Plutonium. Not supported anymore
58int BYTEVERSION_116 = 116; // 1.4 Plutonium. Not supported anymore
59
60int BYTEVERSION_28 = 28; // 1.3 under 1.5 engine
61int BYTEVERSION_117 = 117; // 1.5 Atomic
62
63int BYTEVERSION_29 = 29; // 1.3 under xDuke v19.6.
64int BYTEVERSION_118 = 118; // 1.5 Atomic under xDuke v19.6.
65
66int BYTEVERSION_1_3 = 1; // for 1.3 demos (Not compatible)
67
68int BYTEVERSION = 119; // xDuke v19.7
69
70short global_random;
71short neartagsector, neartagwall, neartagsprite;
72
73int32_t gc,neartaghitdist,lockclock,max_player_health,max_armour_amount,max_ammo_amount[MAX_WEAPONS];
74
75// int32_t temp_data[MAXSPRITES][6];
76struct weaponhit hittype[MAXSPRITES];
77short spriteq[1024],spriteqloc,spriteqamount=64;
78
Franklin Weia855d622017-01-21 15:18:31 -050079struct animwalltype animwall[MAXANIMWALLS];
80short numanimwalls;
81int32_t *animateptr[MAXANIMATES], animategoal[MAXANIMATES], animatevel[MAXANIMATES], animatecnt;
82// int32_t oanimateval[MAXANIMATES];
83short animatesect[MAXANIMATES];
84int32_t msx[2048],msy[2048];
85short cyclers[MAXCYCLERS][6],numcyclers;
86
87char fta_quotes[NUMOFFIRSTTIMEACTIVE][64];
88
89uint8_t tempbuf[2048];
90uint8_t packbuf[576];
91
92char buf[80];
93
94short camsprite;
95short mirrorwall[64], mirrorsector[64], mirrorcnt;
96
97int current_menu;
98
99uint8_t betaname[80];
100
101char level_names[44][33];
102char level_file_names[44][128];
103int32_t partime[44],designertime[44];
104char volume_names[4][33] = { "L.A. MELTDOWN", "LUNAR APOCALYPSE", "SHRAPNEL CITY", "" }; // Names are not in 1.3 con files. MUST be in code.
105char skill_names[5][33] = { "PIECE OF CAKE", "LET'S ROCK", "COME GET SOME", "DAMN I'M GOOD", "" };
106
107volatile int32_t checksume;
108int32_t soundsiz[NUM_SOUNDS];
109
110short soundps[NUM_SOUNDS],soundpe[NUM_SOUNDS],soundvo[NUM_SOUNDS];
111uint8_t soundm[NUM_SOUNDS],soundpr[NUM_SOUNDS];
112char sounds[NUM_SOUNDS][14];
113
114short title_zoom;
115
116fx_device device;
117
118SAMPLE Sound[ NUM_SOUNDS ];
119SOUNDOWNER SoundOwner[NUM_SOUNDS][4];
120
121uint8_t numplayersprites,earthquaketime;
122
123int32_t fricxv,fricyv;
124struct player_orig po[MAXPLAYERS];
125struct player_struct ps[MAXPLAYERS];
126struct user_defs ud;
127
128uint8_t pus, pub;
129uint8_t syncstat, syncval[MAXPLAYERS][MOVEFIFOSIZ];
130int32_t syncvalhead[MAXPLAYERS], syncvaltail, syncvaltottail;
131
132input sync[MAXPLAYERS], loc;
133input recsync[RECSYNCBUFSIZ];
134int32_t avgfvel, avgsvel, avgavel, avghorz, avgbits;
135
136
137input inputfifo[MOVEFIFOSIZ][MAXPLAYERS];
138input recsync[RECSYNCBUFSIZ];
139
140int32_t movefifosendplc;
141
142 //Multiplayer syncing variables
143short screenpeek;
144int32_t movefifoend[MAXPLAYERS];
145
146
147 //Game recording variables
148
149uint8_t playerreadyflag[MAXPLAYERS],ready2send;
150uint8_t playerquitflag[MAXPLAYERS];
151int32_t vel, svel, angvel, horiz, ototalclock, respawnactortime=768, respawnitemtime=768, groupfile;
152
153int32_t script[MAXSCRIPTSIZE],*scriptptr,*insptr,*labelcode,labelcnt;
154int32_t *actorscrptr[MAXTILES],*parsing_actor;
155char *label,*textptr,error,warning ;
156uint8_t killit_flag;
157uint8_t *music_pointer;
158uint8_t actortype[MAXTILES];
159
160
161uint8_t display_mirror,typebuflen;
162char typebuf[41];
163
164char music_fn[4][11][13];
165uint8_t music_select;
166char env_music_fn[4][13];
167uint8_t rtsplaying;
168
169
170short weaponsandammosprites[15] = {
171 RPGSPRITE,
172 CHAINGUNSPRITE,
173 DEVISTATORAMMO,
174 RPGAMMO,
175 RPGAMMO,
176 JETPACK,
177 SHIELD,
178 FIRSTAID,
179 STEROIDS,
180 RPGAMMO,
181 RPGAMMO,
182 RPGSPRITE,
183 RPGAMMO,
184 FREEZESPRITE,
185 FREEZEAMMO
186 };
187
188int32_t impact_damage;
189
190 //GLOBAL.C - replace the end "my's" with this
191int32_t myx, omyx, myxvel, myy, omyy, myyvel, myz, omyz, myzvel;
192short myhoriz, omyhoriz, myhorizoff, omyhorizoff;
193short myang, omyang, mycursectnum, myjumpingcounter,frags[MAXPLAYERS][MAXPLAYERS];
194
195uint8_t myjumpingtoggle, myonground, myhardlanding, myreturntocenter;
196int8_t multiwho, multipos, multiwhat, multiflag;
197
198int32_t fakemovefifoplc,movefifoplc;
199int32_t myxbak[MOVEFIFOSIZ], myybak[MOVEFIFOSIZ], myzbak[MOVEFIFOSIZ];
200int32_t myhorizbak[MOVEFIFOSIZ],dukefriction = 0xcc00, show_shareware;
201
202short myangbak[MOVEFIFOSIZ];
203char myname[2048] = "XDUKE";
204uint8_t camerashitable,freezerhurtowner=0,lasermode;
205// CTW - MODIFICATION
206// uint8_t networkmode = 255, movesperpacket = 1,gamequit = 0,playonten = 0,everyothertime;
207uint8_t networkmode = 255, movesperpacket = 1,gamequit = 0,everyothertime;
208// CTW END - MODIFICATION
209int32_t numfreezebounces=3,rpgblastradius,pipebombblastradius,tripbombblastradius,shrinkerblastradius,morterblastradius,bouncemineblastradius,seenineblastradius;
210STATUSBARTYPE sbar;
211
212int32_t myminlag[MAXPLAYERS], mymaxlag, otherminlag, bufferjitter = 1;
213short numclouds,clouds[128],cloudx[128],cloudy[128];
214int32_t cloudtotalclock = 0,totalmemory = 0;
215int32_t numinterpolations = 0, startofdynamicinterpolations = 0;
216int32_t oldipos[MAXINTERPOLATIONS];
217int32_t bakipos[MAXINTERPOLATIONS];
218int32_t *curipos[MAXINTERPOLATIONS];
219
220
221// portability stuff. --ryan.
222// A good portion of this was ripped from GPL'd Rise of the Triad. --ryan.
223
224#ifndef PATH_SEP_CHAR
225#define PATH_SEP_CHAR '/'
226#endif
227
228void FixFilePath(char *filename)
229{
Franklin Weia855d622017-01-21 15:18:31 -0500230 uint8_t *ptr;
231 uint8_t *lastsep = filename;
232
233 if ((!filename) || (*filename == '\0'))
234 return;
235 if(filename[0] != '/')
236 LOGF("%s is not absolute", filename);
237
238 if (rb->file_exists(filename)) /* File exists; we're good to go. */
239 return;
240
241 for (ptr = filename; 1; ptr++)
242 {
243 if (*ptr == '\\')
244 *ptr = PATH_SEP_CHAR;
245
246 if ((*ptr == PATH_SEP_CHAR) || (*ptr == '\0'))
247 {
248 uint8_t pch = *ptr;
249 struct dirent *dent = NULL;
250 DIR *dir;
251
252 if ((pch == PATH_SEP_CHAR) && (*(ptr + 1) == '\0'))
253 return; /* eos is pathsep; we're done. */
254
255 if (lastsep == ptr)
256 continue; /* absolute path; skip to next one. */
257
258 *ptr = '\0';
259 if (lastsep == filename) {
260 dir = opendir((*lastsep == PATH_SEP_CHAR) ? "/" : "/");
261
262 if (*lastsep == PATH_SEP_CHAR) {
263 lastsep++;
264 }
265 }
266 else
267 {
268 *lastsep = '\0';
269 dir = opendir(filename);
270 *lastsep = PATH_SEP_CHAR;
271 lastsep++;
272 }
273
274 if (dir == NULL)
275 {
276 *ptr = PATH_SEP_CHAR;
277 return; /* maybe dir doesn't exist? give up. */
278 }
279
280 while ((dent = readdir(dir)) != NULL)
281 {
282 if (strcasecmp(dent->d_name, lastsep) == 0)
283 {
284 /* found match; replace it. */
285 strcpy(lastsep, dent->d_name);
286 break;
287 }
288 }
289
290 closedir(dir);
291 *ptr = pch;
292 lastsep = ptr;
293
294 if (dent == NULL)
295 return; /* no match. oh well. */
296
297 if (pch == '\0') /* eos? */
298 return;
299 }
300 }
Franklin Weia855d622017-01-21 15:18:31 -0500301}
302
Franklin Weia855d622017-01-21 15:18:31 -0500303static int check_pattern_nocase(const char *x, const char *y)
304{
305 if ((x == NULL) || (y == NULL))
306 return(0); /* not a match. */
307
308 while ((*x) && (*y))
309 {
310 if (*x == '*')
311 {
312 x++;
313 while (*y != '\0')
314 {
315 if (toupper((int) *x) == toupper((int) *y))
316 break;
317 y++;
318 }
319 }
320
321 else if (*x == '?')
322 {
323 if (*y == '\0')
324 return(0); /* anything but EOS is okay. */
325 }
326
327 else
328 {
329 if (toupper((int) *x) != toupper((int) *y))
330 return(0); /* not a match. */
331 }
332
333 x++;
334 y++;
335 }
336
337 return(*x == *y); /* it's a match (both should be EOS). */
338}
339
Franklin Weia855d622017-01-21 15:18:31 -0500340int FindDistance2D(int ix, int iy)
341{
342 int t;
343
344 ix= abs(ix); /* absolute values */
345 iy= abs(iy);
346
347 if (ix<iy)
348 {
349 int tmp = ix;
350 ix = iy;
351 iy = tmp;
352 }
353
354 t = iy + (iy>>1);
355
356 return (ix - (ix>>5) - (ix>>7) + (t>>2) + (t>>6));
357}
358
359int FindDistance3D(int ix, int iy, int iz)
360{
361 int t;
362
363 ix= abs(ix); /* absolute values */
364 iy= abs(iy);
365 iz= abs(iz);
366
367 if (ix<iy)
368 {
369 int tmp = ix;
370 ix = iy;
371 iy = tmp;
372 }
373
374 if (ix<iz)
375 {
376 int tmp = ix;
377 ix = iz;
378 iz = tmp;
379 }
380
381 t = iy + iz;
382
383 return (ix - (ix>>4) + (t>>2) + (t>>3));
384}
385#include "SDL.h"
386void Error (int errorType, char *error, ...)
387{
388 va_list argptr;
389
390 SDL_Quit();
391
392 //FCS: http://duke3d.m-klein.com is obscolete :/ !
393 /*
394 if(errorType==EXIT_FAILURE)
395 printf("ERROR: Please copy that screen and visit http://duke3d.m-klein.com for report:\n");
396 else
397 printf("http://duke3d.m-klein.com\n");
398 */
399
400
401 va_start (argptr, error);
402 vprintf(error, argptr);
403 va_end (argptr);
404
405 //printf("Press any key to continue...\n");
406
407 // FIX_00043: Nicer exit on error. Ask the user to hit a key on exits and error exits.
408 //getch();
409
410 exit (errorType);
411}
412
413void write2disk(int line, char * cfilename, char *filename2write, char *message)
414{
415 // usage: write2disk(__LINE__, __FILE__, "c:\temp\my_dbug_file.txt", uint8_t * msg);
416
417 int i, k=0;
418 char filename[2048];
419 FILE *pFile;
420
421 for(i=0; cfilename[i]; i++)
422 {
423 if(cfilename[i]=='\\')
424 {
425 i++;
426 k = 0;
427 }
428 filename[k++]=(cfilename[i]=='.')?0:cfilename[i];
429 }
430 pFile = fopen(filename2write,"a");
431 fprintf(pFile,"%-4d %-5s %s", line, filename, message);
432 fclose(pFile);
433}
434
435int32 SafeOpenAppend (const char *_filename, int32 filetype)
436{
437 int handle;
438 char filename[MAX_PATH];
439
440 strncpy(filename, _filename, sizeof (filename));
441 filename[sizeof (filename) - 1] = '\0';
442 FixFilePath(filename);
443
Franklin Weia855d622017-01-21 15:18:31 -0500444 handle = open(filename,O_RDWR | O_BINARY | O_CREAT | O_APPEND , 0666);
Franklin Weia855d622017-01-21 15:18:31 -0500445
446 if (handle == -1)
447 Error (EXIT_FAILURE, "Error opening for append %s: %s",filename,strerror(errno));
448
449 return handle;
450}
451
452boolean SafeFileExists ( const char * _filename )
453{
454 char filename[MAX_PATH];
455 strncpy(filename, _filename, sizeof (filename));
456 filename[sizeof (filename) - 1] = '\0';
457 FixFilePath(filename);
458
Vencislav Atanasov183e45e2019-07-28 23:31:50 +0300459 return(rb->file_exists(filename));
Franklin Weia855d622017-01-21 15:18:31 -0500460}
461
462
463int32 SafeOpenWrite (const char *_filename, int32 filetype)
464{
465 int handle;
466 char filename[MAX_PATH];
467 strncpy(filename, _filename, sizeof (filename));
468 filename[sizeof (filename) - 1] = '\0';
469 FixFilePath(filename);
470
Franklin Weia855d622017-01-21 15:18:31 -0500471 handle = open(filename,O_RDWR | O_BINARY | O_CREAT | O_TRUNC
472 , 0666);
Franklin Weia855d622017-01-21 15:18:31 -0500473
474 if (handle == -1)
475 Error (EXIT_FAILURE, "Error opening %s: %s",filename,strerror(errno));
476
477 return handle;
478}
479
480
481
482
483int32 SafeOpenRead (const char *_filename, int32 filetype)
484{
485 int handle;
486 char filename[MAX_PATH];
487 strncpy(filename, _filename, sizeof (filename));
488 filename[sizeof (filename) - 1] = '\0';
489 FixFilePath(filename);
490
491 handle = open(filename,O_RDONLY | O_BINARY);
492
493 if (handle == -1)
494 Error (EXIT_FAILURE, "Error opening %s: %s",filename,strerror(errno));
495
496 return handle;
497}
498
499
500void SafeRead (int32 handle, void *buffer, int32 count)
501{
502 unsigned iocount;
503
504 while (count)
505 {
506 iocount = count > 0x8000 ? 0x8000 : count;
507 if (read (handle,buffer,iocount) != (int)iocount)
508 Error (EXIT_FAILURE, "File read failure reading %ld bytes",count);
509 buffer = (void *)( (byte *)buffer + iocount );
510 count -= iocount;
511 }
512}
513
514
515void SafeWrite (int32 handle, void *buffer, int32 count)
516{
517 unsigned iocount;
518
519 while (count)
520 {
521 iocount = count > 0x8000 ? 0x8000 : count;
522 if (write (handle,buffer,iocount) != (int)iocount)
523 Error (EXIT_FAILURE, "File write failure writing %ld bytes",count);
524 buffer = (void *)( (byte *)buffer + iocount );
525 count -= iocount;
526 }
527}
528
529void SafeWriteString (int handle, char * buffer)
530{
531 unsigned iocount;
532
533 iocount=strlen(buffer);
534 if (write (handle,buffer,iocount) != (int)iocount)
535 Error (EXIT_FAILURE, "File write string failure writing %s\n",buffer);
536}
537
538void *SafeMalloc (int32_t size)
539{
540 void *ptr;
541
542 ptr = malloc(size);
543
544 if (!ptr)
545 Error (EXIT_FAILURE, "SafeMalloc failure for %lu bytes",size);
546
547 return ptr;
548}
549
550void SafeRealloc (void **x, int32 size)
551{
552 void *ptr;
553
554 ptr = realloc(*x, size);
555
556 if (!ptr)
557 Error (EXIT_FAILURE, "SafeRealloc failure for %lu bytes",size);
558
559 *x = ptr;
560}
561
562void *SafeLevelMalloc (int32_t size)
563{
564 void *ptr;
565
566 ptr = malloc(size);
567
568 if (!ptr)
569 Error (EXIT_FAILURE, "SafeLevelMalloc failure for %lu bytes",size);
570
571 return ptr;
572}
573
574void SafeFree (void * ptr)
575{
576 if ( ptr == NULL )
577 Error (EXIT_FAILURE, "SafeFree : Tried to free a freed pointer\n");
578
579 free(ptr);
580
581}
582
583short SwapShort (short l)
584{
585 byte b1,b2;
586
587 b1 = l&255;
588 b2 = (l>>8)&255;
589
590 return (b1<<8) + b2;
591}
592
593short KeepShort (short l)
594{
595 return l;
596}
597
598
599int32_t Swapint32_t (int32_t l)
600{
601 byte b1,b2,b3,b4;
602
603 b1 = l&255;
604 b2 = (l>>8)&255;
605 b3 = (l>>16)&255;
606 b4 = (l>>24)&255;
607
608 return ((int32_t)b1<<24) + ((int32_t)b2<<16) + ((int32_t)b3<<8) + b4;
609}
610
611int32_t Keepint32_t (int32_t l)
612{
613 return l;
614}
615
616
617#undef KeepShort
618#undef KeepLong
619#undef SwapShort
620#undef SwapLong
621
622void SwapIntelLong(int32_t *l)
623{
624 *l = IntelLong(*l);
625}
626
627void SwapIntelShort(short *s)
628{
629 *s = IntelShort(*s);
630}
631
632void SwapIntelLongArray(int32_t *l, int num)
633{
634 while (num--) {
635 SwapIntelLong(l);
636 l++;
637 }
638}
639
640void SwapIntelShortArray(short *s, int num)
641{
642 while (num--) {
643 SwapIntelShort(s);
644 s++;
645 }
646}
647
648
649/*
650 Copied over from Wolf3D Linux: http://www.icculus.org/wolf3d/
651 Modified for ROTT.
652 Stolen for Duke3D, too.
653 */
654
Franklin Weia855d622017-01-21 15:18:31 -0500655uint8_t *strlwr(uint8_t *s)
656{
657 uint8_t *p = s;
658
659 while (*p) {
660 *p = tolower(*p);
661 p++;
662 }
663
664 return s;
665}
666
667uint8_t *strupr(uint8_t *s)
668{
669 uint8_t *p = s;
670
671 while (*p) {
672 *p = toupper(*p);
673 p++;
674 }
675
676 return s;
677}
678
679uint8_t *itoa(int value, uint8_t *string, int radix)
680{
681 switch (radix) {
682 case 10:
683 sprintf(string, "%d", value);
684 break;
685 case 16:
686 sprintf(string, "%x", value);
687 break;
688 default:
689 STUBBED("unknown radix");
690 break;
691 }
692
693 return string;
694}
695
696uint8_t *ltoa(int32_t value, uint8_t *string, int radix)
697{
698 switch (radix) {
699 case 10:
700 sprintf(string, "%d", value);
701 break;
702 case 16:
703 sprintf(string, "%x", value);
704 break;
705 default:
706 STUBBED("unknown radix");
707 break;
708 }
709
710 return string;
711}
712
713uint8_t *ultoa(uint32_t value, uint8_t *string, int radix)
714{
715 switch (radix) {
716 case 10:
717 sprintf(string, "%u", value);
718 break;
719 case 16:
720 sprintf(string, "%ux", value);
721 break;
722 default:
723 STUBBED("unknown radix");
724 break;
725 }
726
727 return string;
728}
Franklin Weia855d622017-01-21 15:18:31 -0500729
730char ApogeePath[256];
731
732int setup_homedir (void)
733{
Franklin Weia855d622017-01-21 15:18:31 -0500734 int err;
735
736 snprintf (ApogeePath, sizeof (ApogeePath), "%s/.duke3d/", getenv ("HOME"));
737
738 //err = mkdir (ApogeePath, S_IRWXU);
739 err = mkdir (ApogeePath);
740 if (err == -1 && errno != EEXIST)
741 {
742 fprintf (stderr, "Couldn't create preferences directory: %s\n",
743 strerror (errno));
744 return -1;
745 }
Franklin Weia855d622017-01-21 15:18:31 -0500746
747 return 0;
748}
749
750
751uint8_t CheckParm (char *check)
752{
753 int i;
754 for (i = 1; i < _argc; i++)
755 {
756 if ((*(_argv[i]) == '-') && (strcmpi(_argv[i] + 1, check) == 0))
757 return(i);
758 }
759
760 return(0);
761}
762
763
764static void (*shutdown_func)(void) = NULL;
765
766void RegisterShutdownFunction( void (* shutdown) (void) )
767{
768 shutdown_func = shutdown;
769}
770
771void Shutdown(void)
772{
773 if (shutdown_func != NULL)
774 {
775 shutdown_func();
776 shutdown_func = NULL;
777 }
778}
779
780