1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 1996, 2005 - 3D Realms Entertainment
4 
5 This file is NOT part of Shadow Warrior version 1.2
6 However, it is either an older version of a file that is, or is
7 some test code written during the development of Shadow Warrior.
8 This file is provided purely for educational interest.
9 
10 Shadow Warrior is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
14 
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 
19 See the GNU General Public License for more details.
20 
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24 
25 Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
26 */
27 //-------------------------------------------------------------------------
28 
29 // scriplib.c
30 #include "build.h"
31 #include "editor.h"
32 #include "cache1d.h"
33 
34 #include "names2.h"
35 #include "game.h"
36 
37 #include "parse.h"
38 
39 #define PATHSEPERATOR   '\\'
40 
41 
42 //#define COMPUTE_TOTALS	1
43 
44 /*
45 =============================================================================
46 
47 						ABNORMAL TERMINATION
48 
49 =============================================================================
50 */
Error(char * error,...)51 void Error (char *error, ...)
52 {
53 	va_list argptr;
54 
55 	va_start (argptr,error);
56 	vprintf (error,argptr);
57 	va_end (argptr);
58 	printf ("\n");
59 	exit (1);
60 }
61 
62 
63 
64 /*
65 =============================================================================
66 
67 						PARSING STUFF
68 
69 =============================================================================
70 */
71 
72 char    token[MAXTOKEN];
73 char    *scriptbuffer,*script_p,*scriptend_p;
74 int     grabbed;
75 int     scriptline;
76 BOOL    endofscript;
77 BOOL    tokenready;                     // only TRUE if UnGetToken was just called
78 
79 /*
80 ==============
81 =
82 = LoadScriptFile
83 =
84 ==============
85 */
86 
LoadScriptFile(char * filename)87 BOOL LoadScriptFile (char *filename)
88 {
89 	int size, readsize;
90 	int fp;
91 
92 
93 	if((fp=kopen4load(filename,0)) == -1)
94 	{
95 		// If there's no script file, forget it.
96 		return FALSE;
97 	}
98 
99     size = kfilelength(fp);
100 
101     scriptbuffer = (char *)malloc(size);
102 
103 	ASSERT(scriptbuffer != NULL);
104 
105 	readsize = kread(fp, scriptbuffer, size);
106 
107     kclose(fp);
108 
109 	ASSERT(readsize == size);
110 
111 
112 	// Convert filebuffer to all upper case
113 	//strupr(scriptbuffer);
114 
115 	script_p = scriptbuffer;
116 	scriptend_p = script_p + size;
117 	scriptline = 1;
118 	endofscript = FALSE;
119 	tokenready = FALSE;
120 	return TRUE;
121 }
122 
123 
124 /*
125 ==============
126 =
127 = UnGetToken
128 =
129 = Signals that the current token was not used, and should be reported
130 = for the next GetToken.  Note that
131 
132 GetToken (TRUE);
133 UnGetToken ();
134 GetToken (FALSE);
135 
136 = could cross a line boundary.
137 =
138 ==============
139 */
140 
UnGetToken(void)141 void UnGetToken (void)
142 {
143 	tokenready = TRUE;
144 }
145 
146 
147 /*
148 ==============
149 =
150 = GetToken
151 =
152 ==============
153 */
154 
GetToken(BOOL crossline)155 void GetToken (BOOL crossline)
156 {
157 	char    *token_p;
158 
159 	if (tokenready)                         // is a token already waiting?
160 	{
161 		tokenready = FALSE;
162 		return;
163 	}
164 
165 	if (script_p >= scriptend_p)
166 	{
167 		if (!crossline)
168 			Error ("Line %i is incomplete\n",scriptline);
169 		endofscript = TRUE;
170 		return;
171 	}
172 
173 //
174 // skip space
175 //
176 skipspace:
177 	while (*script_p <= 32)
178 	{
179 		if (script_p >= scriptend_p)
180 		{
181 			if (!crossline)
182 				Error ("Line %i is incomplete\n",scriptline);
183 			endofscript = TRUE;
184 			return;
185 		}
186 		if (*script_p++ == '\n')
187 		{
188 			if (!crossline)
189 				Error ("Line %i is incomplete\n",scriptline);
190 			scriptline++;
191 		}
192 	}
193 
194 	if (script_p >= scriptend_p)
195 	{
196 		if (!crossline)
197 			Error ("Line %i is incomplete\n",scriptline);
198 		endofscript = TRUE;
199 		return;
200 	}
201 
202 	if (*script_p == '#')   // # is comment field
203 	{
204 		if (!crossline)
205 			Error ("Line %i is incomplete\n",scriptline);
206 		while (*script_p++ != '\n')
207 			if (script_p >= scriptend_p)
208 			{
209 				endofscript = TRUE;
210 				return;
211 			}
212 		goto skipspace;
213 	}
214 
215 //
216 // copy token
217 //
218 	token_p = token;
219 
220 	while ( *script_p > 32 && *script_p != '#')
221 	{
222 		*token_p++ = *script_p++;
223 		if (script_p == scriptend_p)
224 			break;
225 		ASSERT (token_p != &token[MAXTOKEN]);
226 //			Error ("Token too large on line %i\n",scriptline);
227 	}
228 
229 	*token_p = 0;
230 }
231 
232 
233 /*
234 ==============
235 =
236 = TokenAvailable
237 =
238 = Returns true if there is another token on the line
239 =
240 ==============
241 */
242 
TokenAvailable(void)243 BOOL TokenAvailable (void)
244 {
245 	char    *search_p;
246 
247 	search_p = script_p;
248 
249 	if (search_p >= scriptend_p)
250 		return FALSE;
251 
252 	while ( *search_p <= 32)
253 	{
254 		if (*search_p == '\n')
255 			return FALSE;
256 		search_p++;
257 		if (search_p == scriptend_p)
258 			return FALSE;
259 
260 	}
261 
262 	if (*search_p == '#')
263 		return FALSE;
264 
265 	return TRUE;
266 }
267 
DefaultExtension(char * path,char * extension)268 void DefaultExtension (char *path, char *extension)
269 {
270 	char    *src;
271 //
272 // if path doesn't have a .EXT, append extension
273 // (extension should include the .)
274 //
275 	src = path + strlen(path) - 1;
276 
277 	while (*src != '\\' && src != path)
278 	{
279 		if (*src == '.')
280 			return;                 // it has an extension
281 		src--;
282 	}
283 
284 	strcat (path, extension);
285 }
286 
287 
DefaultPath(char * path,char * basepath)288 void DefaultPath (char *path, char *basepath)
289 {
290 	char    temp[128];
291 
292 	if (path[0] == '\\')
293 		return;                                                 // absolute path location
294 	strcpy (temp,path);
295 	strcpy (path,basepath);
296 	strcat (path,temp);
297 }
298 
299 
StripFilename(char * path)300 void    StripFilename (char *path)
301 {
302 	int             length;
303 
304 	length = strlen(path)-1;
305 	while (length > 0 && path[length] != PATHSEPERATOR)
306 		length--;
307 	path[length] = 0;
308 }
309 
310 
ExtractFileBase(char * path,char * dest)311 void ExtractFileBase (char *path, char *dest)
312 {
313 	char    *src;
314 	int             length;
315 
316 	src = path + strlen(path) - 1;
317 
318 //
319 // back up until a \ or the start
320 //
321 	while (src != path && *(src-1) != '\\')
322 		src--;
323 
324 //
325 // copy up to eight characters
326 //
327 	memset (dest,0,8);
328 	length = 0;
329 	while (*src && *src != '.')
330 	{
331 		if (++length == 9)
332 			Error ("Filename base of %s >8 chars",path);
333 		*dest++ = toupper(*src++);
334 	}
335 }
336 
337 
338 /*
339 ==============
340 =
341 = ParseNum / ParseHex
342 =
343 ==============
344 */
345 
ParseHex(char * hex)346 int ParseHex (char *hex)
347 {
348 	char    *str;
349 	int    num;
350 
351 	num = 0;
352 	str = hex;
353 
354 	while (*str)
355 	{
356 		num <<= 4;
357 		if (*str >= '0' && *str <= '9')
358 			num += *str-'0';
359 		else if (*str >= 'a' && *str <= 'f')
360 			num += 10 + *str-'a';
361 		else if (*str >= 'A' && *str <= 'F')
362 			num += 10 + *str-'A';
363 		else
364 			Error ("Bad hex number: %s",hex);
365 		str++;
366 	}
367 
368 	return num;
369 }
370 
371 
ParseNum(char * str)372 int ParseNum (char *str)
373 {
374 	if (str[0] == '$')
375 		return ParseHex (str+1);
376 	if (str[0] == '0' && str[1] == 'x')
377 		return ParseHex (str+2);
378 	return atol (str);
379 }
380 
381 
382 
383 
384 // voxelarray format is:
385 //  	spritenumber, voxelnumber
386 int aVoxelArray[MAXTILES];
387 
388 extern int nextvoxid;
389 
390 // Load all the voxel files using swvoxfil.txt script file
391 // Script file format:
392 
393 //			# - Comment
394 //			spritenumber (in artfile), voxel number, filename
395 //			Ex. 1803 0 medkit2.kvx
396 //			    1804 1 shotgun.kvx
397 //				etc....
398 
LoadKVXFromScript(char * filename)399 void LoadKVXFromScript( char *filename )
400 {
401 	int lNumber=0,lTile=0;	// lNumber is the voxel no. and lTile is the editart tile being
402 							// replaced.
403 	char *sName;			// KVS file being loaded in.
404 
405 	int grabbed=0;			// Number of lines parsed
406 
407 	sName = (char *)malloc(256);	// Up to 256 bytes for path
408 	ASSERT(sName != NULL);
409 
410 	// zero out the array memory with -1's for pics not being voxelized
411 	memset(aVoxelArray,-1,sizeof(aVoxelArray));
412 
413 	// Load the file
414 	if (!LoadScriptFile(filename)) return;
415 
416 	do {
417 		GetToken (TRUE);	// Crossing a line boundary on the end of line to first token
418 							// of a new line is permitted (and expected)
419 		if (endofscript)
420 			break;
421 
422 		lTile = atol(token);
423 
424 		GetToken(FALSE);
425 		lNumber = atol(token);
426 
427 		GetToken(FALSE);
428 		strcpy(sName,token);			// Copy the whole token as a file name and path
429 
430 		// Load the voxel file into memory
431 		if (!qloadkvx(lNumber,sName)) {
432 			// Store the sprite and voxel numbers for later use
433 			aVoxelArray[lTile] = lNumber;	// Voxel num
434 		}
435 
436 		if (lNumber >= nextvoxid)	// JBF: so voxels in the def file append to the list
437 			nextvoxid = lNumber + 1;
438 
439 		grabbed++;
440 		ASSERT(grabbed < MAXSPRITES);
441 
442 	} while (script_p < scriptend_p);
443 
444 	free(scriptbuffer);
445 	script_p = NULL;
446 }
447 
448 
449 /// MISC ////////////////////////////////////////////////////////////////////
450 
451 /*
452 extern int idleclock,slackerclock;
453 
454 // Watch dog function.  Tracks user's work times.
455 void LogUserTime( BOOL bIsLoggingIn )
456 {
457 	int size, readsize;
458 	time_t time_of_day;
459     char serialid[20],filename[100],fbase[20],buf[26],filetemp[100];
460     FILE *fp;
461 	int tothours, totmins, totsecs, gtotalclock=0,gidleclock=0;
462 	ldiv_t mins_secs;
463 	ldiv_t hrs_mins;
464 	int i;
465 
466 	char path[] = "o:\\user\\jimn\\logs\\";
467 //	char path[] = "c:\\jim\\sw\\";
468 
469 	memset(filename,0,sizeof(filename));
470 	memset(fbase,0,sizeof(fbase));
471 	memset(serialid,0,sizeof(serialid));
472 	memset(buf,0,sizeof(buf));
473 	memset(filetemp,0,sizeof(filetemp));
474 
475 	// Get the time of day user logged in to build
476     time_of_day = time( NULL );
477 
478 	// Get the serial number from the user's disk drive "it's unique!"
479 	system("dir > serid.bld");
480 	LoadScriptFile("serid.bld");
481 
482 	// Go to the serial number
483 	for (i=0; i<11; i++)
484 	{
485 		GetToken (TRUE);
486 		if (endofscript)
487 			return;
488 	}
489 
490 	// Copy the token to serialid
491 	strcpy(serialid,token);
492 
493 	// Free the script memory when done
494 	free(scriptbuffer);
495 	script_p = NULL;
496 
497 	// Build a file name using serial id.
498 	strcpy(filename,path);
499 	strncpy(fbase,serialid,8);
500 	strcat(fbase,".bld");
501 	strcat(filename,fbase);
502 
503 	// Delete the temp file
504 	system("erase serid.bld");
505 
506 	// Unhide the file so it can be opened
507 	_dos_setfileattr(filename,_A_NORMAL);
508 
509 
510 	// Open the file
511 	fp = fopen( filename, "a+" );
512 
513 	// Opening on the network failed, try putting it on the current disk drive
514 	if(fp == NULL)
515 	{
516 		// Unhide the file so it can be opened/this works if file was created before!
517 		_dos_setfileattr(fbase,_A_NORMAL);
518 		fp = fopen( fbase, "a+" );
519 		strcpy(filetemp,fbase);
520 	} else
521 		strcpy(filetemp,filename);
522 
523 
524   	if( fp == NULL)
525    		return;
526 	else
527     {
528 		if(bIsLoggingIn)
529 		{
530 			fprintf(fp, "//////////////////////////////\n");
531 		    fprintf(fp, "User logged into build at: %s", _ctime( &time_of_day, buf ) );
532 		}else
533 		{
534 			totsecs = totalclock/120;	// Convert totalclock to seconds.
535 
536 			mins_secs = ldiv( totsecs, 60L );
537 			totmins = mins_secs.quot;
538 			totsecs = mins_secs.rem;
539 
540 			hrs_mins = ldiv( totmins, 60L);
541 			tothours = hrs_mins.quot;
542 			totmins = hrs_mins.rem;
543 
544 			fprintf(fp, "TotalClock: %ld\n",totalclock);
545 #ifdef COMPUTE_TOTALS
546 			fprintf(fp, "IdleClock: %ld\n",slackerclock);
547 #endif
548 			fprintf(fp, "Time this session: %ld Hours %ld Mins %ld Secs\n",tothours,totmins,totsecs);
549 #ifdef COMPUTE_TOTALS
550 			totsecs = (totalclock-slackerclock)/120;	// Convert totalclock to seconds.
551 			if(totsecs<=0) totsecs = 0;
552 
553 			mins_secs = ldiv( totsecs, 60L );
554 			totmins = mins_secs.quot;
555 			totsecs = mins_secs.rem;
556 
557 			hrs_mins = ldiv( totmins, 60L);
558 			tothours = hrs_mins.quot;
559 			totmins = hrs_mins.rem;
560 			fprintf(fp, "Time - idleclock : %ld Hours %ld Mins %ld Secs\n",tothours,totmins,totsecs);
561 #endif
562 		}
563 
564 	    fclose( fp );
565 	}
566 
567 #if 1
568 	if(!bIsLoggingIn)
569 	{
570 		// Compute total time for file
571 		LoadScriptFile(filetemp);
572 
573 		do {
574 			GetToken (TRUE);
575 
576 			if (endofscript)
577 				break;
578 
579 			if(!strcmpi(token,"totalclock:"))
580 			{
581 				GetToken(TRUE);
582 				gtotalclock += atol(token);
583 			}
584 #if 0
585 			if(!strcmpi(token,"idleclock:"))
586 			{
587 				GetToken(TRUE);
588 				gidleclock += atol(token);
589 			}
590 #endif
591 
592 		} while (script_p < scriptend_p);
593 
594 		// Free the script memory when done
595 		free(scriptbuffer);
596 		script_p = NULL;
597 
598 		// Open the file
599 		fp = fopen( filetemp, "a+" );
600 
601 		// Now compute the grand total
602 		if(fp != NULL)
603 		{
604 			totsecs = gtotalclock/120;	// Convert totalclock to seconds.
605 
606 			mins_secs = ldiv( totsecs, 60L );
607 			totmins = mins_secs.quot;
608 			totsecs = mins_secs.rem;
609 
610 			hrs_mins = ldiv( totmins, 60L);
611 			tothours = hrs_mins.quot;
612 			totmins = hrs_mins.rem;
613 
614 			fprintf(fp, "\nTotal time so far  : %ld Hours %ld Mins %ld Secs\n",tothours,totmins,totsecs);
615 
616 #if 0
617 			totsecs = (gtotalclock-gidleclock)/120;	// Convert totalclock to seconds.
618 			if(totsecs<=0) totsecs = 0;
619 
620 			mins_secs = ldiv( totsecs, 60L );
621 			totmins = mins_secs.quot;
622 			totsecs = mins_secs.rem;
623 
624 			hrs_mins = ldiv( totmins, 60L);
625 			tothours = hrs_mins.quot;
626 			totmins = hrs_mins.rem;
627 
628 			fprintf(fp, "\nTotal actual time  : %ld Hours %ld Mins %ld Secs\n",tothours,totmins,totsecs);
629 #endif
630 
631 			fclose(fp);
632 		}
633 	}
634 #endif
635 
636 	_dos_setfileattr(filename,_A_HIDDEN);
637 
638 
639 }
640 */
641