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