common.c 56.7 KB
Newer Older
Tyrann's avatar
Tyrann committed
1
2
/*
Copyright (C) 1996-1997 Id Software, Inc.
3
4
Copyright (C) 2002-2009 John Fitzgibbons and others
Copyright (C) 2010-2014 QuakeSpasm developers
Tyrann's avatar
Tyrann committed
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/
// common.c -- misc functions used in client and server
23
#include <stdio.h>
24
#include <ctype.h>
Libretro-Admin's avatar
Libretro-Admin committed
25
#include <retro_dirent.h>
26
#include <stdarg.h>
27
#include <stdlib.h>
Tyrann's avatar
Tyrann committed
28
#include <string.h>
29
#include <sys/types.h>
30
#include <errno.h>
Tyrann's avatar
Tyrann committed
31

32
#ifdef NQ_HACK
33
34
#include "quakedef.h"
#include "host.h"
35
36
37
38
39
40
41
42
43
44
#endif
#ifdef QW_HACK
#ifdef SERVERONLY
#include "qwsvdef.h"
#include "server.h"
#else
#include "quakedef.h"
#endif
#include "protocol.h"
#endif
45

Tyrann's avatar
Tyrann committed
46
47
48
49
50
51
#include "cmd.h"
#include "common.h"
#include "console.h"
#include "crc.h"
#include "draw.h"
#include "net.h"
Tyrann's avatar
Tyrann committed
52
#include "shell.h"
Tyrann's avatar
Tyrann committed
53
54
55
#include "sys.h"
#include "zone.h"

56
#define NUM_SAFE_ARGVS 7
Tyrann's avatar
Tyrann committed
57

58
59
static const char *largv[MAX_NUM_ARGVS + NUM_SAFE_ARGVS + 1];
static const char *argvdummy = " ";
Tyrann's avatar
Tyrann committed
60

61
static const char *safeargvs[NUM_SAFE_ARGVS] = {
62
  "-stdvid", "-nolan", "-nosound", "-nocdaudio", "-nojoy", "-nomouse", "-dibonly"
Tyrann's avatar
Tyrann committed
63
64
65
};

cvar_t registered = { "registered", "0" };
66
#ifdef NQ_HACK
Tyrann's avatar
Tyrann committed
67
static cvar_t cmdline = { "cmdline", "0", false, true };
68
#endif
Tyrann's avatar
Tyrann committed
69
70
71
72
73
74
75
76

static qboolean com_modified;		// set true if using non-id files
static int static_registered = 1;	// only for startup check, then set

qboolean msg_suppress_1 = 0;

static void COM_InitFilesystem(void);
static void COM_Path_f(void);
77
static void *SZ_GetSpace(sizebuf_t *buf, int length);
Tyrann's avatar
Tyrann committed
78
79
80

// if a packfile directory differs from this, it is assumed to be hacked
#define PAK0_COUNT		339
81
82
#define NQ_PAK0_CRC		32981
#define QW_PAK0_CRC		52883
Tyrann's avatar
Tyrann committed
83

84
#ifdef NQ_HACK
Tyrann's avatar
Tyrann committed
85
86
#define CMDLINE_LENGTH	256
static char com_cmdline[CMDLINE_LENGTH];
87
#endif
Tyrann's avatar
Tyrann committed
88
89
90

qboolean standard_quake = true, rogue, hipnotic;

91
92
93
94
#ifdef QW_HACK
char gamedirfile[MAX_OSPATH];
#endif

Tyrann's avatar
Tyrann committed
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/*

All of Quake's data access is through a hierchal file system, but the contents
of the file system can be transparently merged from several sources.

The "base directory" is the path to the directory holding the quake.exe and
all game directories.  The sys_* files pass this to host_init in
quakeparms_t->basedir.  This can be overridden with the "-basedir" command
line parm to allow code debugging in a different directory.  The base
directory is only used during filesystem initialization.

The "game directory" is the first tree on the search path and directory that
all generated files (savegames, screenshots, demos, config files) will be
saved to.  This can be overridden with the "-game" command line parameter.
The game directory can never be changed while quake is executing.  This is a
precacution against having a malicious server instruct clients to write files
over areas they shouldn't.

*/

//============================================================================


// ClearLink is used for new headnodes
Libretro-Admin's avatar
Libretro-Admin committed
119
void ClearLink(link_t *l)
Tyrann's avatar
Tyrann committed
120
{
Libretro-Admin's avatar
Libretro-Admin committed
121
   l->prev = l->next = l;
Tyrann's avatar
Tyrann committed
122
123
}

Libretro-Admin's avatar
Libretro-Admin committed
124
void RemoveLink(link_t *l)
Tyrann's avatar
Tyrann committed
125
{
Libretro-Admin's avatar
Libretro-Admin committed
126
127
   l->next->prev = l->prev;
   l->prev->next = l->next;
Tyrann's avatar
Tyrann committed
128
129
}

Libretro-Admin's avatar
Libretro-Admin committed
130
void InsertLinkBefore(link_t *l, link_t *before)
Tyrann's avatar
Tyrann committed
131
{
Libretro-Admin's avatar
Libretro-Admin committed
132
133
134
135
   l->next = before;
   l->prev = before->prev;
   l->prev->next = l;
   l->next->prev = l;
Tyrann's avatar
Tyrann committed
136
137
138
139
}

/* Unused */
#if 0
Libretro-Admin's avatar
Libretro-Admin committed
140
void InsertLinkAfter(link_t *l, link_t *after)
Tyrann's avatar
Tyrann committed
141
{
Libretro-Admin's avatar
Libretro-Admin committed
142
143
144
145
   l->next = after->next;
   l->prev = after;
   l->prev->next = l;
   l->next->prev = l;
Tyrann's avatar
Tyrann committed
146
147
148
149
150
151
152
153
154
155
156
}
#endif

/*
============================================================================

			LIBRARY REPLACEMENT FUNCTIONS

============================================================================
*/

157
158
159
160
161
162
/*
 * Use this function to share static string buffers
 * between different text processing functions.
 * Try to avoid fixed-size intermediate buffers like this if possible
 */
#define COM_STRBUF_LEN 2048
Libretro-Admin's avatar
Libretro-Admin committed
163
static char *COM_GetStrBuf(void)
164
{
Libretro-Admin's avatar
Libretro-Admin committed
165
166
167
   static char buffers[4][COM_STRBUF_LEN];
   static int index;
   return buffers[3 & ++index];
168
169
}

Libretro-Admin's avatar
Libretro-Admin committed
170
171
172
173
174
int Q_atoi(const char *str)
{
   int val;
   int sign;
   int c;
175

Libretro-Admin's avatar
Libretro-Admin committed
176
177
178
179
180
181
   if (*str == '-')
   {
      sign = -1;
      str++;
   } else
      sign = 1;
182

Libretro-Admin's avatar
Libretro-Admin committed
183
   val = 0;
Tyrann's avatar
Tyrann committed
184

Libretro-Admin's avatar
Libretro-Admin committed
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
   // check for hex
   if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
   {
      str += 2;
      while (1)
      {
         c = *str++;
         if (c >= '0' && c <= '9')
            val = (val << 4) + c - '0';
         else if (c >= 'a' && c <= 'f')
            val = (val << 4) + c - 'a' + 10;
         else if (c >= 'A' && c <= 'F')
            val = (val << 4) + c - 'A' + 10;
         else
            return val * sign;
      }
   }
Tyrann's avatar
Tyrann committed
202

Libretro-Admin's avatar
Libretro-Admin committed
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
   // check for character
   if (str[0] == '\'')
      return sign * str[1];

   // assume decimal
   while (1)
   {
      c = *str++;
      if (c < '0' || c > '9')
         return val * sign;
      val = val * 10 + c - '0';
   }

   return 0;
}


float Q_atof(const char *str)
{
   double val;
   int sign;
   int c;
   int decimal, total;

   if (*str == '-')
   {
      sign = -1;
      str++;
   }
   else
      sign = 1;

   val = 0;

   // check for hex
   if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
   {
      str += 2;
      while (1)
      {
         c = *str++;
         if (c >= '0' && c <= '9')
            val = (val * 16) + c - '0';
         else if (c >= 'a' && c <= 'f')
            val = (val * 16) + c - 'a' + 10;
         else if (c >= 'A' && c <= 'F')
            val = (val * 16) + c - 'A' + 10;
         else
            return val * sign;
      }
   }

   // check for character
   if (str[0] == '\'')
      return sign * str[1];

   // assume decimal
   decimal = -1;
   total = 0;
   while (1)
   {
      c = *str++;
      if (c == '.')
      {
         decimal = total;
         continue;
      }
      if (c < '0' || c > '9')
         break;
      val = val * 10 + c - '0';
      total++;
   }

   if (decimal == -1)
      return val * sign;

   while (total > decimal)
   {
      val /= 10;
      total--;
   }
Tyrann's avatar
Tyrann committed
284

Libretro-Admin's avatar
Libretro-Admin committed
285
   return val * sign;
Tyrann's avatar
Tyrann committed
286
287
288
289
290
291
292
293
294
295
296
}

/*
==============================================================================

			MESSAGE IO FUNCTIONS

Handles byte ordering and avoids alignment errors
==============================================================================
*/

297
298
299
300
#ifdef QW_HACK
usercmd_t nullcmd;		// guarenteed to be zero
#endif

Tyrann's avatar
Tyrann committed
301
302
// writing functions

Libretro-Admin's avatar
Libretro-Admin committed
303
void MSG_WriteChar(sizebuf_t *sb, int c)
Tyrann's avatar
Tyrann committed
304
{
Libretro-Admin's avatar
Libretro-Admin committed
305
306
   byte *buf = (byte*)SZ_GetSpace(sb, 1);
   buf[0] = c;
Tyrann's avatar
Tyrann committed
307
308
}

Libretro-Admin's avatar
Libretro-Admin committed
309
void MSG_WriteByte(sizebuf_t *sb, int c)
Tyrann's avatar
Tyrann committed
310
{
Libretro-Admin's avatar
Libretro-Admin committed
311
312
   byte *buf = (byte*)SZ_GetSpace(sb, 1);
   buf[0] = c;
Tyrann's avatar
Tyrann committed
313
314
}

Libretro-Admin's avatar
Libretro-Admin committed
315
void MSG_WriteShort(sizebuf_t *sb, int c)
Tyrann's avatar
Tyrann committed
316
{
Libretro-Admin's avatar
Libretro-Admin committed
317
318
319
   byte *buf = (byte*)SZ_GetSpace(sb, 2);
   buf[0] = c & 0xff;
   buf[1] = c >> 8;
Tyrann's avatar
Tyrann committed
320
321
}

Libretro-Admin's avatar
Libretro-Admin committed
322
void MSG_WriteLong(sizebuf_t *sb, int c)
Tyrann's avatar
Tyrann committed
323
{
Libretro-Admin's avatar
Libretro-Admin committed
324
325
326
327
328
   byte *buf = (byte*)SZ_GetSpace(sb, 4);
   buf[0] = c & 0xff;
   buf[1] = (c >> 8) & 0xff;
   buf[2] = (c >> 16) & 0xff;
   buf[3] = c >> 24;
Tyrann's avatar
Tyrann committed
329
330
}

Libretro-Admin's avatar
Libretro-Admin committed
331
void MSG_WriteFloat(sizebuf_t *sb, float f)
Tyrann's avatar
Tyrann committed
332
{
333
334
335
336
337
#ifdef MSB_FIRST
   union {
      float f;
      int l;
   } dat;
Tyrann's avatar
Tyrann committed
338

339
340
   dat.f = f;
   dat.l = LittleLong(dat.l);
Tyrann's avatar
Tyrann committed
341

342
343
344
345
   SZ_Write(sb, &dat.l, 4);
#else
   SZ_Write (sb, &f, 4);
#endif
Tyrann's avatar
Tyrann committed
346
347
}

Libretro-Admin's avatar
Libretro-Admin committed
348
void MSG_WriteString(sizebuf_t *sb, const char *s)
Tyrann's avatar
Tyrann committed
349
{
Libretro-Admin's avatar
Libretro-Admin committed
350
351
352
353
   if (!s)
      SZ_Write(sb, "", 1);
   else
      SZ_Write(sb, s, strlen(s) + 1);
Tyrann's avatar
Tyrann committed
354
355
}

Libretro-Admin's avatar
Libretro-Admin committed
356
void MSG_WriteStringvf(sizebuf_t *sb, const char *fmt, va_list ap)
357
{
Libretro-Admin's avatar
Libretro-Admin committed
358
359
360
361
362
363
364
   /*
    * FIXME - Kind of ugly to check space first then do getspace
    * afterwards, but we don't know how much we'll need before
    * hand. Update the SZ interface?
    */
   int maxlen = sb->maxsize - sb->cursize;
   int    len = vsnprintf((char *)sb->data + sb->cursize, maxlen, fmt, ap);
365

Libretro-Admin's avatar
Libretro-Admin committed
366
367
   /* Use SZ_GetSpace to check for overflow */
   SZ_GetSpace(sb, len + 1);
368
369
}

Libretro-Admin's avatar
Libretro-Admin committed
370
void MSG_WriteStringf(sizebuf_t *sb, const char *fmt, ...)
371
{
Libretro-Admin's avatar
Libretro-Admin committed
372
   va_list ap;
373

Libretro-Admin's avatar
Libretro-Admin committed
374
375
376
   va_start(ap, fmt);
   MSG_WriteStringvf(sb, fmt, ap);
   va_end(ap);
377
378
}

Libretro-Admin's avatar
Libretro-Admin committed
379
void MSG_WriteCoord(sizebuf_t *sb, float f)
Tyrann's avatar
Tyrann committed
380
{
Libretro-Admin's avatar
Libretro-Admin committed
381
382
383
384
385
   /*
    * Co-ords are send as shorts, with the low 3 bits being the fractional
    * component
    */
   MSG_WriteShort(sb, (int)(f * (1 << 3)));
Tyrann's avatar
Tyrann committed
386
387
}

Libretro-Admin's avatar
Libretro-Admin committed
388
void MSG_WriteAngle(sizebuf_t *sb, float f)
Tyrann's avatar
Tyrann committed
389
{
Libretro-Admin's avatar
Libretro-Admin committed
390
   MSG_WriteByte(sb, (int)floorf((f * 256 / 360) + 0.5f) & 255);
Tyrann's avatar
Tyrann committed
391
392
}

Libretro-Admin's avatar
Libretro-Admin committed
393
void MSG_WriteAngle16(sizebuf_t *sb, float f)
394
{
Libretro-Admin's avatar
Libretro-Admin committed
395
   MSG_WriteShort(sb, (int)floorf((f * 65536 / 360) + 0.5f) & 65535);
396
397
}

398
#ifdef QW_HACK
Libretro-Admin's avatar
Libretro-Admin committed
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
void MSG_WriteDeltaUsercmd(sizebuf_t *buf, const usercmd_t *from,
      const usercmd_t *cmd)
{
   // send the movement message
   int bits = 0;
   if (cmd->angles[0] != from->angles[0])
      bits |= CM_ANGLE1;
   if (cmd->angles[1] != from->angles[1])
      bits |= CM_ANGLE2;
   if (cmd->angles[2] != from->angles[2])
      bits |= CM_ANGLE3;
   if (cmd->forwardmove != from->forwardmove)
      bits |= CM_FORWARD;
   if (cmd->sidemove != from->sidemove)
      bits |= CM_SIDE;
   if (cmd->upmove != from->upmove)
      bits |= CM_UP;
   if (cmd->buttons != from->buttons)
      bits |= CM_BUTTONS;
   if (cmd->impulse != from->impulse)
      bits |= CM_IMPULSE;

   MSG_WriteByte(buf, bits);

   if (bits & CM_ANGLE1)
      MSG_WriteAngle16(buf, cmd->angles[0]);
   if (bits & CM_ANGLE2)
      MSG_WriteAngle16(buf, cmd->angles[1]);
   if (bits & CM_ANGLE3)
      MSG_WriteAngle16(buf, cmd->angles[2]);

   if (bits & CM_FORWARD)
      MSG_WriteShort(buf, cmd->forwardmove);
   if (bits & CM_SIDE)
      MSG_WriteShort(buf, cmd->sidemove);
   if (bits & CM_UP)
      MSG_WriteShort(buf, cmd->upmove);

   if (bits & CM_BUTTONS)
      MSG_WriteByte(buf, cmd->buttons);
   if (bits & CM_IMPULSE)
      MSG_WriteByte(buf, cmd->impulse);
   MSG_WriteByte(buf, cmd->msec);
442
443
444
}
#endif /* QW_HACK */

445
446
447
448
449
#ifdef NQ_HACK
/*
 * Write the current message length to the start of the buffer (in big
 * endian format) with the control flag set.
 */
Libretro-Admin's avatar
Libretro-Admin committed
450
void MSG_WriteControlHeader(sizebuf_t *sb)
451
{
Libretro-Admin's avatar
Libretro-Admin committed
452
   int c = NETFLAG_CTL | (sb->cursize & NETFLAG_LENGTH_MASK);
453

Libretro-Admin's avatar
Libretro-Admin committed
454
455
456
457
   sb->data[0] = c >> 24;
   sb->data[1] = (c >> 16) & 0xff;
   sb->data[2] = (c >> 8) & 0xff;
   sb->data[3] = c & 0xff;
458
459
460
}
#endif

Tyrann's avatar
Tyrann committed
461
462
463
464
// reading functions
int msg_readcount;
qboolean msg_badread;

Libretro-Admin's avatar
Libretro-Admin committed
465
void MSG_BeginReading(void)
Tyrann's avatar
Tyrann committed
466
{
Libretro-Admin's avatar
Libretro-Admin committed
467
468
   msg_readcount = 0;
   msg_badread = false;
Tyrann's avatar
Tyrann committed
469
470
}

471
#ifdef QW_HACK
Libretro-Admin's avatar
Libretro-Admin committed
472
int MSG_GetReadCount(void)
473
{
Libretro-Admin's avatar
Libretro-Admin committed
474
   return msg_readcount;
475
476
477
}
#endif

Tyrann's avatar
Tyrann committed
478
// returns -1 and sets msg_badread if no more characters are available
Libretro-Admin's avatar
Libretro-Admin committed
479
int MSG_ReadChar(void)
Tyrann's avatar
Tyrann committed
480
{
Libretro-Admin's avatar
Libretro-Admin committed
481
   int c;
Tyrann's avatar
Tyrann committed
482

Libretro-Admin's avatar
Libretro-Admin committed
483
   if (msg_readcount + 1 > net_message.cursize)
Libretro-Admin's avatar
Libretro-Admin committed
484
      goto error;
Tyrann's avatar
Tyrann committed
485

Libretro-Admin's avatar
Libretro-Admin committed
486
487
   c = (signed char)net_message.data[msg_readcount];
   msg_readcount++;
Tyrann's avatar
Tyrann committed
488

Libretro-Admin's avatar
Libretro-Admin committed
489
   return c;
Libretro-Admin's avatar
Libretro-Admin committed
490
491
492
493

error:
   msg_badread = true;
   return -1;
Tyrann's avatar
Tyrann committed
494
495
}

Libretro-Admin's avatar
Libretro-Admin committed
496
int MSG_ReadByte(void)
Tyrann's avatar
Tyrann committed
497
{
Libretro-Admin's avatar
Libretro-Admin committed
498
   int c;
Tyrann's avatar
Tyrann committed
499

Libretro-Admin's avatar
Libretro-Admin committed
500
   if (msg_readcount + 1 > net_message.cursize)
Libretro-Admin's avatar
Libretro-Admin committed
501
      goto error;
Tyrann's avatar
Tyrann committed
502

Libretro-Admin's avatar
Libretro-Admin committed
503
504
   c = (unsigned char)net_message.data[msg_readcount];
   msg_readcount++;
Tyrann's avatar
Tyrann committed
505

Libretro-Admin's avatar
Libretro-Admin committed
506
   return c;
Libretro-Admin's avatar
Libretro-Admin committed
507
508
509
510

error:
   msg_badread = true;
   return -1;
Tyrann's avatar
Tyrann committed
511
512
}

Libretro-Admin's avatar
Libretro-Admin committed
513
int MSG_ReadShort(void)
Tyrann's avatar
Tyrann committed
514
{
Libretro-Admin's avatar
Libretro-Admin committed
515
   int c;
Tyrann's avatar
Tyrann committed
516

Libretro-Admin's avatar
Libretro-Admin committed
517
   if (msg_readcount + 2 > net_message.cursize)
Libretro-Admin's avatar
Libretro-Admin committed
518
      goto error;
Tyrann's avatar
Tyrann committed
519

Libretro-Admin's avatar
Libretro-Admin committed
520
521
   c = (short)(net_message.data[msg_readcount]
         + (net_message.data[msg_readcount + 1] << 8));
Tyrann's avatar
Tyrann committed
522

Libretro-Admin's avatar
Libretro-Admin committed
523
   msg_readcount += 2;
Tyrann's avatar
Tyrann committed
524

Libretro-Admin's avatar
Libretro-Admin committed
525
   return c;
Libretro-Admin's avatar
Libretro-Admin committed
526
527
528
529

error:
   msg_badread = true;
   return -1;
Tyrann's avatar
Tyrann committed
530
531
}

Libretro-Admin's avatar
Libretro-Admin committed
532
int MSG_ReadLong(void)
Tyrann's avatar
Tyrann committed
533
{
Libretro-Admin's avatar
Libretro-Admin committed
534
   int c;
Tyrann's avatar
Tyrann committed
535

Libretro-Admin's avatar
Libretro-Admin committed
536
   if (msg_readcount + 4 > net_message.cursize)
Libretro-Admin's avatar
Libretro-Admin committed
537
      goto error;
Tyrann's avatar
Tyrann committed
538

Libretro-Admin's avatar
Libretro-Admin committed
539
540
541
542
   c = net_message.data[msg_readcount]
   + (net_message.data[msg_readcount + 1] << 8)
   + (net_message.data[msg_readcount + 2] << 16)
   + (net_message.data[msg_readcount + 3] << 24);
Tyrann's avatar
Tyrann committed
543

Libretro-Admin's avatar
Libretro-Admin committed
544
   msg_readcount += 4;
Tyrann's avatar
Tyrann committed
545

Libretro-Admin's avatar
Libretro-Admin committed
546
   return c;
Libretro-Admin's avatar
Libretro-Admin committed
547
548
549
550

error:
   msg_badread = true;
   return -1;
Tyrann's avatar
Tyrann committed
551
552
}

Libretro-Admin's avatar
Libretro-Admin committed
553
float MSG_ReadFloat(void)
Tyrann's avatar
Tyrann committed
554
{
555
556
557
558
559
560
561
   union {
      byte b[4];
      float f;
#ifdef MSB_FIRST
      int l;
#endif
   } dat;
Tyrann's avatar
Tyrann committed
562

563
564
565
566
567
   dat.b[0] = net_message.data[msg_readcount];
   dat.b[1] = net_message.data[msg_readcount + 1];
   dat.b[2] = net_message.data[msg_readcount + 2];
   dat.b[3] = net_message.data[msg_readcount + 3];
   msg_readcount += 4;
Tyrann's avatar
Tyrann committed
568

569
570
571
#ifdef MSB_FIRST
   dat.l = LittleLong(dat.l);
#endif
Tyrann's avatar
Tyrann committed
572

573
   return dat.f;
Tyrann's avatar
Tyrann committed
574
575
}

Libretro-Admin's avatar
Libretro-Admin committed
576
char *MSG_ReadString(void)
Tyrann's avatar
Tyrann committed
577
{
Libretro-Admin's avatar
Libretro-Admin committed
578
579
   char *buf = COM_GetStrBuf();
   int len   = 0;
Tyrann's avatar
Tyrann committed
580

Libretro-Admin's avatar
Libretro-Admin committed
581
582
   do
   {
Libretro-Admin's avatar
Libretro-Admin committed
583
      int c = MSG_ReadChar();
Libretro-Admin's avatar
Libretro-Admin committed
584
585
586
      if (c == -1 || c == 0)
         break;
      buf[len++] = c;
Libretro-Admin's avatar
Libretro-Admin committed
587
   }while (len < COM_STRBUF_LEN - 1);
Libretro-Admin's avatar
Libretro-Admin committed
588
589

   buf[len] = 0;
Tyrann's avatar
Tyrann committed
590

Libretro-Admin's avatar
Libretro-Admin committed
591
   return buf;
Tyrann's avatar
Tyrann committed
592
593
}

594
#ifdef QW_HACK
Libretro-Admin's avatar
Libretro-Admin committed
595
char *MSG_ReadStringLine(void)
596
{
Libretro-Admin's avatar
Libretro-Admin committed
597
598
599
600
   char *buf = COM_GetStrBuf();
   int len = 0;

   do {
Libretro-Admin's avatar
Libretro-Admin committed
601
      int c = MSG_ReadChar();
Libretro-Admin's avatar
Libretro-Admin committed
602
603
604
605
      if (c == -1 || c == 0 || c == '\n')
         break;
      buf[len++] = c;
   } while (len < COM_STRBUF_LEN - 1);
606

Libretro-Admin's avatar
Libretro-Admin committed
607
   buf[len] = 0;
608

Libretro-Admin's avatar
Libretro-Admin committed
609
   return buf;
610
611
612
}
#endif

Libretro-Admin's avatar
Libretro-Admin committed
613
float MSG_ReadCoord(void)
Tyrann's avatar
Tyrann committed
614
{
Libretro-Admin's avatar
Libretro-Admin committed
615
616
617
618
619
   /*
    * Co-ords are send as shorts, with the low 3 bits being the fractional
    * component
    */
   return MSG_ReadShort() * (1.0 / (1 << 3));
Tyrann's avatar
Tyrann committed
620
621
}

Libretro-Admin's avatar
Libretro-Admin committed
622
float MSG_ReadAngle(void)
Tyrann's avatar
Tyrann committed
623
{
Libretro-Admin's avatar
Libretro-Admin committed
624
   return MSG_ReadChar() * (360.0 / 256);
Tyrann's avatar
Tyrann committed
625
626
}

Libretro-Admin's avatar
Libretro-Admin committed
627
float MSG_ReadAngle16(void)
628
{
Libretro-Admin's avatar
Libretro-Admin committed
629
   return MSG_ReadShort() * (360.0 / 65536);
630
631
}

632
#ifdef QW_HACK
Libretro-Admin's avatar
Libretro-Admin committed
633
void MSG_ReadDeltaUsercmd(const usercmd_t *from, usercmd_t *move)
634
{
Libretro-Admin's avatar
Libretro-Admin committed
635
   int bits;
636

Libretro-Admin's avatar
Libretro-Admin committed
637
   memcpy(move, from, sizeof(*move));
638

Libretro-Admin's avatar
Libretro-Admin committed
639
   bits = MSG_ReadByte();
640

Libretro-Admin's avatar
Libretro-Admin committed
641
642
643
644
645
646
647
   // read current angles
   if (bits & CM_ANGLE1)
      move->angles[0] = MSG_ReadAngle16();
   if (bits & CM_ANGLE2)
      move->angles[1] = MSG_ReadAngle16();
   if (bits & CM_ANGLE3)
      move->angles[2] = MSG_ReadAngle16();
648

Libretro-Admin's avatar
Libretro-Admin committed
649
650
651
652
653
654
655
   // read movement
   if (bits & CM_FORWARD)
      move->forwardmove = MSG_ReadShort();
   if (bits & CM_SIDE)
      move->sidemove = MSG_ReadShort();
   if (bits & CM_UP)
      move->upmove = MSG_ReadShort();
656

Libretro-Admin's avatar
Libretro-Admin committed
657
658
659
   // read buttons
   if (bits & CM_BUTTONS)
      move->buttons = MSG_ReadByte();
Tyrann's avatar
Tyrann committed
660

Libretro-Admin's avatar
Libretro-Admin committed
661
662
   if (bits & CM_IMPULSE)
      move->impulse = MSG_ReadByte();
663

Libretro-Admin's avatar
Libretro-Admin committed
664
665
   // read time to run command
   move->msec = MSG_ReadByte();
666
667
}
#endif /* QW_HACK */
Tyrann's avatar
Tyrann committed
668

669
670
671
672
673
#ifdef NQ_HACK
/*
 * Read back the message control header
 * Essentially this is MSG_ReadLong, but big-endian byte order.
 */
Libretro-Admin's avatar
Libretro-Admin committed
674
int MSG_ReadControlHeader(void)
675
{
Libretro-Admin's avatar
Libretro-Admin committed
676
   int c;
677

Libretro-Admin's avatar
Libretro-Admin committed
678
679
680
681
682
   if (msg_readcount + 4 > net_message.cursize)
   {
      msg_badread = true;
      return -1;
   }
683

Libretro-Admin's avatar
Libretro-Admin committed
684
685
686
687
   c = (net_message.data[msg_readcount] << 24)
      + (net_message.data[msg_readcount + 1] << 16)
      + (net_message.data[msg_readcount + 2] << 8)
      + net_message.data[msg_readcount + 3];
688

Libretro-Admin's avatar
Libretro-Admin committed
689
   msg_readcount += 4;
690

Libretro-Admin's avatar
Libretro-Admin committed
691
   return c;
692
693
694
}
#endif

Tyrann's avatar
Tyrann committed
695
696
//===========================================================================

697
#ifdef NQ_HACK
Libretro-Admin's avatar
Libretro-Admin committed
698
void SZ_Alloc(sizebuf_t *buf, int startsize)
Tyrann's avatar
Tyrann committed
699
{
Libretro-Admin's avatar
Libretro-Admin committed
700
701
702
703
704
   if (startsize < 256)
      startsize = 256;
   buf->data = (byte*)Hunk_AllocName(startsize, "sizebuf");
   buf->maxsize = startsize;
   buf->cursize = 0;
Tyrann's avatar
Tyrann committed
705
706
}

Libretro-Admin's avatar
Libretro-Admin committed
707
void SZ_Free(sizebuf_t *buf)
Tyrann's avatar
Tyrann committed
708
{
Libretro-Admin's avatar
Libretro-Admin committed
709
710
711
712
   //      Z_Free (buf->data);
   //      buf->data = NULL;
   //      buf->maxsize = 0;
   buf->cursize = 0;
Tyrann's avatar
Tyrann committed
713
}
714
#endif
Tyrann's avatar
Tyrann committed
715

Libretro-Admin's avatar
Libretro-Admin committed
716
void SZ_Clear(sizebuf_t *buf)
Tyrann's avatar
Tyrann committed
717
{
Libretro-Admin's avatar
Libretro-Admin committed
718
719
   buf->cursize = 0;
   buf->overflowed = false;
Tyrann's avatar
Tyrann committed
720
721
}

Libretro-Admin's avatar
Libretro-Admin committed
722
static void *SZ_GetSpace(sizebuf_t *buf, int length)
Tyrann's avatar
Tyrann committed
723
{
Libretro-Admin's avatar
Libretro-Admin committed
724
   void *data;
Tyrann's avatar
Tyrann committed
725

Libretro-Admin's avatar
Libretro-Admin committed
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
   if (buf->cursize + length > buf->maxsize)
   {
      if (!buf->allowoverflow)
         Sys_Error("%s: overflow without allowoverflow set (%d > %d)",
               __func__, buf->cursize + length, buf->maxsize);
      if (length > buf->maxsize)
         Sys_Error("%s: %d is > full buffer size", __func__, length);
      if (developer.value)
         /* Con_Printf may be redirected */
         Sys_Printf("%s: overflow\n", __func__);
      SZ_Clear(buf);
      buf->overflowed = true;
   }
   data = buf->data + buf->cursize;
   buf->cursize += length;
Tyrann's avatar
Tyrann committed
741

Libretro-Admin's avatar
Libretro-Admin committed
742
   return data;
Tyrann's avatar
Tyrann committed
743
744
}

Libretro-Admin's avatar
Libretro-Admin committed
745
void SZ_Write(sizebuf_t *buf, const void *data, int length)
Tyrann's avatar
Tyrann committed
746
{
Libretro-Admin's avatar
Libretro-Admin committed
747
   memcpy(SZ_GetSpace(buf, length), data, length);
Tyrann's avatar
Tyrann committed
748
749
}

Libretro-Admin's avatar
Libretro-Admin committed
750
void SZ_Print(sizebuf_t *buf, const char *data)
Tyrann's avatar
Tyrann committed
751
{
Libretro-Admin's avatar
Libretro-Admin committed
752
   size_t len = strlen(data);
Tyrann's avatar
Tyrann committed
753

Libretro-Admin's avatar
Libretro-Admin committed
754
755
756
757
758
   /* If buf->data has a trailing zero, overwrite it */
   if (!buf->cursize || buf->data[buf->cursize - 1])
      memcpy(SZ_GetSpace(buf, len + 1), data, len + 1);
   else
      memcpy((byte*)SZ_GetSpace(buf, len) - 1, data, len + 1);
Tyrann's avatar
Tyrann committed
759
760
761
762
763
764
765
766
767
768
769
}


//============================================================================


/*
============
COM_SkipPath
============
*/
Libretro-Admin's avatar
Libretro-Admin committed
770
const char *COM_SkipPath(const char *pathname)
Tyrann's avatar
Tyrann committed
771
{
Libretro-Admin's avatar
Libretro-Admin committed
772
773
774
775
776
777
778
779
   const char *last = pathname;
   while (*pathname)
   {
      if (*pathname == '/')
         last = pathname + 1;
      pathname++;
   }
   return last;
Tyrann's avatar
Tyrann committed
780
781
782
783
784
785
786
}

/*
============
COM_StripExtension
============
*/
Libretro-Admin's avatar
Libretro-Admin committed
787
void COM_StripExtension(char *filename)
Tyrann's avatar
Tyrann committed
788
{
Libretro-Admin's avatar
Libretro-Admin committed
789
790
791
792
   const char *start = COM_SkipPath(filename);
   char *pos = (char*)strrchr(start, '.');
   if (pos && *pos)
      *pos = 0;
Tyrann's avatar
Tyrann committed
793
794
795
796
797
798
799
}

/*
============
COM_FileExtension
============
*/
800
#ifdef NQ_HACK
801
const char *COM_FileExtension(const char *in)
Tyrann's avatar
Tyrann committed
802
{
Libretro-Admin's avatar
Libretro-Admin committed
803
804
805
   static char exten[8];
   const char *dot;
   int i;
Tyrann's avatar
Tyrann committed
806

Libretro-Admin's avatar
Libretro-Admin committed
807
808
809
810
   in = COM_SkipPath(in);
   dot = strrchr(in, '.');
   if (!dot)
      return "";
811

Libretro-Admin's avatar
Libretro-Admin committed
812
813
814
815
   dot++;
   for (i = 0; i < sizeof(exten) - 1 && *dot; i++, dot++)
      exten[i] = *dot;
   exten[i] = 0;
816

Libretro-Admin's avatar
Libretro-Admin committed
817
   return exten;
Tyrann's avatar
Tyrann committed
818
}
819
#endif
Tyrann's avatar
Tyrann committed
820
821
822
823
824
825

/*
============
COM_FileBase
============
*/
Libretro-Admin's avatar
Libretro-Admin committed
826
void COM_FileBase(const char *in, char *out, size_t buflen)
Tyrann's avatar
Tyrann committed
827
{
Libretro-Admin's avatar
Libretro-Admin committed
828
829
   const char *dot;
   int copylen;
Tyrann's avatar
Tyrann committed
830

Libretro-Admin's avatar
Libretro-Admin committed
831
832
833
   in = COM_SkipPath(in);
   dot = strrchr(in, '.');
   copylen = dot ? dot - in : strlen(in);
Tyrann's avatar
Tyrann committed
834

Libretro-Admin's avatar
Libretro-Admin committed
835
836
837
838
839
   if (copylen < 2) {
      in = "?model?";
      copylen = strlen(in);
   }
   snprintf(out, buflen, "%.*s", copylen, in);
Tyrann's avatar
Tyrann committed
840
841
842
843
844
845
846
847
}


/*
==================
COM_DefaultExtension
==================
*/
Libretro-Admin's avatar
Libretro-Admin committed
848
849
850
851
852
853
854
855
856
857
858
859
void COM_DefaultExtension(char *path, const char *extension)
{
   // if path doesn't have a .EXT, append extension
   // (extension should include the .)
   const char *src = path + strlen(path) - 1;
   while (*src != '/' && src != path)
   {
      if (*src == '.')
         return;		// it has an extension
      src--;
   }
   strcat(path, extension);
Tyrann's avatar
Tyrann committed
860
861
}

Libretro-Admin's avatar
Libretro-Admin committed
862
int COM_CheckExtension(const char *path, const char *extn)
863
{
Libretro-Admin's avatar
Libretro-Admin committed
864
865
   int ret   = 0;
   char *pos = (char*)strrchr(path, '.');
866

Libretro-Admin's avatar
Libretro-Admin committed
867
868
869
870
871
872
   if (pos)
   {
      if (extn[0] != '.')
         pos++;
      ret = pos && !strcasecmp(pos, extn);
   }
873

Libretro-Admin's avatar
Libretro-Admin committed
874
   return ret;
875
876
}

Tyrann's avatar
Tyrann committed
877
878
879
880
//============================================================================

char com_token[1024];
unsigned com_argc;
881
const char **com_argv;
Tyrann's avatar
Tyrann committed
882
883
884
885
886
887
888
889

/*
==============
COM_Parse

Parse a token out of a string
==============
*/
890
891
static const char single_chars[] = "{})(':";

Libretro-Admin's avatar
Libretro-Admin committed
892
static const char *COM_Parse_(const char *data, qboolean split_single_chars)
Tyrann's avatar
Tyrann committed
893
{
Libretro-Admin's avatar
Libretro-Admin committed
894
895
   int c;
   int len = 0;
Tyrann's avatar
Tyrann committed
896

Libretro-Admin's avatar
Libretro-Admin committed
897
   com_token[0] = 0;
Tyrann's avatar
Tyrann committed
898

Libretro-Admin's avatar
Libretro-Admin committed
899
900
   if (!data)
      return NULL;
Tyrann's avatar
Tyrann committed
901

Libretro-Admin's avatar
Libretro-Admin committed
902
903
904
905
906
907
908
   // skip whitespace
skipwhite:
   while ((c = *data) <= ' ') {
      if (c == 0)
         return NULL;	// end of file;
      data++;
   }
Tyrann's avatar
Tyrann committed
909

Libretro-Admin's avatar
Libretro-Admin committed
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
   // skip // comments
   if (c == '/' && data[1] == '/') {
      while (*data && *data != '\n')
         data++;
      goto skipwhite;
   }
   // handle quoted strings specially
   if (c == '\"') {
      data++;
      while (1) {
         c = *data++;
         if (c == '\"' || !c) {
            com_token[len] = 0;
            return data;
         }
         com_token[len] = c;
         len++;
      }
   }
   // parse single characters
   if (split_single_chars && strchr(single_chars, c)) {
      com_token[len] = c;
      len++;
      com_token[len] = 0;
      return data + 1;
   }
   // parse a regular word
   do {
      com_token[len] = c;
      data++;
      len++;
      c = *data;
      if (split_single_chars && strchr(single_chars, c))
         break;
   } while (c > 32);
Tyrann's avatar
Tyrann committed
945

Libretro-Admin's avatar
Libretro-Admin committed
946
947
   com_token[len] = 0;
   return data;
Tyrann's avatar
Tyrann committed
948
949
}

950
951
952
953
954
955
956
957
958
959
const char *
COM_Parse(const char *data)
{
#ifdef NQ_HACK
    return COM_Parse_(data, true);
#endif
#ifdef QW_HACK
    return COM_Parse_(data, false);
#endif
}
Tyrann's avatar
Tyrann committed
960
961
962
963
964
965
966
967
968

/*
================
COM_CheckParm

Returns the position (1 to argc-1) in the program's argument list
where the given parameter apears, or 0 if not present
================
*/
Libretro-Admin's avatar
Libretro-Admin committed
969
unsigned COM_CheckParm(const char *parm)
Tyrann's avatar
Tyrann committed
970
{
Libretro-Admin's avatar
Libretro-Admin committed
971
   unsigned i;
Tyrann's avatar
Tyrann committed
972

Libretro-Admin's avatar
Libretro-Admin committed
973
974
975
976
977
978
   for (i = 1; i < com_argc; i++) {
      if (!com_argv[i])
         continue;		// NEXTSTEP sometimes clears appkit vars.
      if (!strcmp(parm, com_argv[i]))
         return i;
   }
Tyrann's avatar
Tyrann committed
979

Libretro-Admin's avatar
Libretro-Admin committed
980
   return 0;
Tyrann's avatar
Tyrann committed
981
982
983
984
985
986
987
988
989
990
991
992
}

/*
================
COM_CheckRegistered

Looks for the pop.txt file and verifies it.
Sets the "registered" cvar.
Immediately exits out if an alternate game was attempted to be started without
being registered.
================
*/
Libretro-Admin's avatar
Libretro-Admin committed
993
void COM_CheckRegistered(void)
Tyrann's avatar
Tyrann committed
994
{
995
   FILE *f;
Tyrann's avatar
Tyrann committed
996

997
#ifdef NQ_HACK
998
   Cvar_Set("cmdline", com_cmdline);
999
#endif
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
   COM_FOpenFile("gfx/pop.lmp", &f);
   if (!f)
      Con_Printf("Playing shareware version.\n");
   else
   {
      fclose(f);
      Cvar_Set("registered", "1");
      static_registered = 1;
      Con_Printf("Playing registered version.\n");
   }
Tyrann's avatar
Tyrann committed
1010
1011
1012
1013
1014
1015
1016
1017
}


/*
================
COM_InitArgv
================
*/
Libretro-Admin's avatar
Libretro-Admin committed
1018
void COM_InitArgv(int argc, const char **argv)
Tyrann's avatar
Tyrann committed
1019
{
Libretro-Admin's avatar
Libretro-Admin committed
1020
1021
   qboolean safe;
   int i;
1022
#ifdef NQ_HACK
Libretro-Admin's avatar
Libretro-Admin committed
1023
   int j, n = 0;
Libretro-Admin's avatar
Libretro-Admin committed
1024
   // reconstitute the command line for the cmdline externally visible cvar
Libretro-Admin's avatar
Libretro-Admin committed
1025
1026
   for (j = 0; (j < MAX_NUM_ARGVS) && (j < argc); j++)
   {
Libretro-Admin's avatar
Libretro-Admin committed
1027
      i = 0;
Libretro-Admin's avatar
Libretro-Admin committed
1028
      while ((n < (CMDLINE_LENGTH - 1)) && argv[j][i])
Libretro-Admin's avatar
Libretro-Admin committed
1029
1030
1031
1032
1033
1034
1035
1036
         com_cmdline[n++] = argv[j][i++];

      if (n < (CMDLINE_LENGTH - 1))
         com_cmdline[n++] = ' ';
      else
         break;
   }
   com_cmdline[n] = 0;
1037
#endif
Tyrann's avatar
Tyrann committed
1038

Libretro-Admin's avatar
Libretro-Admin committed
1039
   safe = false;
Tyrann's avatar
Tyrann committed
1040

Libretro-Admin's avatar
Libretro-Admin committed
1041
1042
1043
1044
1045
1046
   for (com_argc = 0; (com_argc < MAX_NUM_ARGVS) && (com_argc < argc);
         com_argc++) {
      largv[com_argc] = argv[com_argc];
      if (!strcmp("-safe", argv[com_argc]))
         safe = true;
   }
Tyrann's avatar
Tyrann committed
1047

Libretro-Admin's avatar
Libretro-Admin committed
1048
1049
1050
1051
1052
1053
1054
1055
   if (safe) {
      // force all the safe-mode switches. Note that we reserved extra space in
      // case we need to add these, so we don't need an overflow check
      for (i = 0; i < NUM_SAFE_ARGVS; i++) {
         largv[com_argc] = safeargvs[i];
         com_argc++;
      }
   }
Tyrann's avatar
Tyrann committed
1056

Libretro-Admin's avatar
Libretro-Admin committed
1057
1058
   largv[com_argc] = argvdummy;
   com_argv = largv;
Tyrann's avatar
Tyrann committed
1059

1060
#ifdef NQ_HACK
Libretro-Admin's avatar
Libretro-Admin committed
1061
1062
1063
1064
   if (COM_CheckParm("-rogue")) {
      rogue = true;
      standard_quake = false;
   }
Tyrann's avatar
Tyrann committed
1065

Libretro-Admin's avatar
Libretro-Admin committed
1066
1067
1068
1069
   if (COM_CheckParm("-hipnotic") || COM_CheckParm("-quoth")) {
      hipnotic = true;
      standard_quake = false;
   }
1070
#endif
Tyrann's avatar
Tyrann committed
1071
1072
}

1073
1074
1075
1076
1077
1078
1079
1080
/*
================
COM_AddParm

Adds the given string at the end of the current argument list
================
*/
#ifdef QW_HACK
Libretro-Admin's avatar
Libretro-Admin committed
1081
void COM_AddParm(const char *parm)
1082
{
Libretro-Admin's avatar
Libretro-Admin committed
1083
   largv[com_argc++] = parm;
1084
1085
}
#endif
Tyrann's avatar
Tyrann committed
1086
1087
1088
1089
1090
1091

/*
================
COM_Init
================
*/
twinaphex's avatar
twinaphex committed
1092

Libretro-Admin's avatar
Libretro-Admin committed
1093
void COM_Init(void)
Tyrann's avatar
Tyrann committed
1094
{
Libretro-Admin's avatar
Libretro-Admin committed
1095
   Cvar_RegisterVariable(&registered);
1096
#ifdef NQ_HACK
Libretro-Admin's avatar
Libretro-Admin committed
1097
   Cvar_RegisterVariable(&cmdline);
1098
#endif
Libretro-Admin's avatar
Libretro-Admin committed
1099
   Cmd_AddCommand("path", COM_Path_f);
Tyrann's avatar
Tyrann committed
1100

Libretro-Admin's avatar
Libretro-Admin committed
1101
1102
   COM_InitFilesystem();
   COM_CheckRegistered();
Tyrann's avatar
Tyrann committed
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
}


/*
============
va

does a varargs printf into a temp buffer, so I don't need to have
varargs versions of all text functions.
============
*/
1114
char *va(const char *format, ...)
Tyrann's avatar
Tyrann committed
1115
{
Libretro-Admin's avatar
Libretro-Admin committed
1116
1117
   va_list argptr;
   int len;
Libretro-Admin's avatar
Libretro-Admin committed
1118
   char *buf = COM_GetStrBuf();
Tyrann's avatar
Tyrann committed
1119

Libretro-Admin's avatar
Libretro-Admin committed
1120
1121
1122
   va_start(argptr, format);
   len = vsnprintf(buf, COM_STRBUF_LEN, format, argptr);
   va_end(argptr);
Tyrann's avatar
Tyrann committed
1123

Libretro-Admin's avatar
Libretro-Admin committed
1124
1125
   if (len > COM_STRBUF_LEN - 1)
      Con_DPrintf("%s: overflow (string truncated)\n", __func__);
Tyrann's avatar
Tyrann committed
1126

Libretro-Admin's avatar
Libretro-Admin committed
1127
   return buf;
Tyrann's avatar
Tyrann committed
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
}


/*
=============================================================================

QUAKE FILESYSTEM

=============================================================================
*/

int com_filesize;

// in memory

typedef struct {
    char name[MAX_QPATH];
    int filepos, filelen;
} packfile_t;

Libretro-Admin's avatar
Libretro-Admin committed
1148
1149
typedef struct pack_s
{
Tyrann's avatar
Tyrann committed
1150
1151
1152
1153
1154
1155
    char filename[MAX_OSPATH];
    int numfiles;
    packfile_t *files;
} pack_t;

// on disk
1156
#define MAX_PACKPATH 56
Libretro-Admin's avatar
Libretro-Admin committed
1157
1158
typedef struct
{
1159
    char name[MAX_PACKPATH];
Tyrann's avatar
Tyrann committed
1160
1161
1162
    int filepos, filelen;
} dpackfile_t;

Libretro-Admin's avatar
Libretro-Admin committed
1163
1164
typedef struct
{
Tyrann's avatar
Tyrann committed
1165
1166
1167
1168
1169
1170
    char id[4];
    int dirofs;
    int dirlen;
} dpackheader_t;

char com_gamedir[MAX_OSPATH];
Tyrann's avatar
Tyrann committed
1171
char com_basedir[MAX_OSPATH];
1172
char com_savedir[MAX_OSPATH];
Tyrann's avatar
Tyrann committed
1173
1174
1175
1176
1177
1178
1179

typedef struct searchpath_s {
    char filename[MAX_OSPATH];
    pack_t *pack;		// only one of filename / pack will be used
    struct searchpath_s *next;
} searchpath_t;

Tyrann's avatar
Tyrann committed
1180
static searchpath_t *com_searchpaths;