Subversion Repositories eduke32

Rev

Rev 3243 | Rev 3321 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2542 helixhorne 1
//
2
// Common non-engine code/data for EDuke32 and Mapster32
3
//
4
 
5
#include "compat.h"
2726 hendricks2 6
#include "build.h"
2549 helixhorne 7
#include "scriptfile.h"
2554 helixhorne 8
#include "cache1d.h"
9
#include "kplib.h"
10
#include "baselayer.h"
3220 hendricks2 11
#include "names.h"
2542 helixhorne 12
 
13
#include "common.h"
2726 hendricks2 14
#include "common_game.h"
2542 helixhorne 15
 
2789 hendricks2 16
int32_t g_gameType = GAMEFLAG_DUKE;
2542 helixhorne 17
 
2726 hendricks2 18
// grp/con/def handling
19
 
2796 helixhorne 20
const char *defaultgamegrp[GAMECOUNT] = { "DUKE3D.GRP", "NAM.GRP", "NAPALM.GRP", "WW2GI.GRP" };
21
const char *defaultdeffilename[GAMECOUNT] = { "duke3d.def", "nam.def", "napalm.def", "ww2gi.def" };
22
const char *defaultconfilename = "GAME.CON";
23
const char *defaultgameconfilename[GAMECOUNT] = { "EDUKE.CON", "NAM.CON", "NAPALM.CON", "WW2GI.CON" };
2726 hendricks2 24
 
25
// g_grpNamePtr can ONLY point to a malloc'd block (length BMAX_PATH)
26
char *g_grpNamePtr = NULL;
27
// g_defNamePtr can ONLY point to a malloc'd block (length BMAX_PATH)
28
char *g_defNamePtr = NULL;
29
// g_scriptNamePtr can ONLY point to a malloc'd block (length BMAX_PATH)
30
char *g_scriptNamePtr = NULL;
31
 
32
void clearGrpNamePtr(void)
33
{
34
    if (g_grpNamePtr != NULL)
35
        Bfree(g_grpNamePtr);
36
    // g_grpNamePtr assumed to be assigned to right after
37
}
38
 
39
void clearDefNamePtr(void)
40
{
41
    if (g_defNamePtr != NULL)
42
        Bfree(g_defNamePtr);
43
    // g_defNamePtr assumed to be assigned to right after
44
}
45
 
46
void clearScriptNamePtr(void)
47
{
48
    if (g_scriptNamePtr != NULL)
49
        Bfree(g_scriptNamePtr);
50
    // g_scriptNamePtr assumed to be assigned to right after
51
}
52
 
2796 helixhorne 53
const char *G_DefaultGrpFile(void)
2726 hendricks2 54
{
55
    if (DUKE)
56
        return defaultgamegrp[GAME_DUKE];
57
    // order is important for the following three because GAMEFLAG_NAM overlaps all
58
    else if (NAPALM)
59
        return defaultgamegrp[GAME_NAPALM];
60
    else if (WW2GI)
61
        return defaultgamegrp[GAME_WW2GI];
62
    else if (NAM)
63
        return defaultgamegrp[GAME_NAM];
64
 
65
    return defaultgamegrp[0];
66
}
2796 helixhorne 67
const char *G_DefaultDefFile(void)
2726 hendricks2 68
{
69
    if (DUKE)
70
        return defaultdeffilename[GAME_DUKE];
71
    else if (WW2GI)
72
        return defaultdeffilename[GAME_WW2GI];
73
    else if (NAPALM)
74
    {
2752 helixhorne 75
        if (!testkopen(defaultdeffilename[GAME_NAPALM],0) && testkopen(defaultdeffilename[GAME_NAM],0))
2726 hendricks2 76
            return defaultdeffilename[GAME_NAM]; // NAM/Napalm Sharing
77
        else
78
            return defaultdeffilename[GAME_NAPALM];
79
    }
80
    else if (NAM)
81
    {
2752 helixhorne 82
        if (!testkopen(defaultdeffilename[GAME_NAM],0) && testkopen(defaultdeffilename[GAME_NAPALM],0))
2726 hendricks2 83
            return defaultdeffilename[GAME_NAPALM]; // NAM/Napalm Sharing
84
        else
85
            return defaultdeffilename[GAME_NAM];
86
    }
87
 
88
    return defaultdeffilename[0];
89
}
2796 helixhorne 90
const char *G_DefaultConFile(void)
2726 hendricks2 91
{
2752 helixhorne 92
    if (DUKE && testkopen(defaultgameconfilename[GAME_DUKE],0))
2726 hendricks2 93
        return defaultgameconfilename[GAME_DUKE];
2752 helixhorne 94
    else if (WW2GI && testkopen(defaultgameconfilename[GAME_WW2GI],0))
2726 hendricks2 95
        return defaultgameconfilename[GAME_WW2GI];
96
    else if (NAPALM)
97
    {
2752 helixhorne 98
        if (!testkopen(defaultgameconfilename[GAME_NAPALM],0))
2726 hendricks2 99
        {
2752 helixhorne 100
            if (testkopen(defaultgameconfilename[GAME_NAM],0))
2726 hendricks2 101
                return defaultgameconfilename[GAME_NAM]; // NAM/Napalm Sharing
102
        }
103
        else
104
            return defaultgameconfilename[GAME_NAPALM];
105
    }
106
    else if (NAM)
107
    {
2752 helixhorne 108
        if (!testkopen(defaultgameconfilename[GAME_NAM],0))
2726 hendricks2 109
        {
2752 helixhorne 110
            if (testkopen(defaultgameconfilename[GAME_NAPALM],0))
2726 hendricks2 111
                return defaultgameconfilename[GAME_NAPALM]; // NAM/Napalm Sharing
112
        }
113
        else
114
            return defaultgameconfilename[GAME_NAM];
115
    }
116
 
117
    return defaultconfilename;
118
}
119
 
2796 helixhorne 120
const char *G_GrpFile(void)
2726 hendricks2 121
{
122
    if (g_grpNamePtr == NULL)
123
        return G_DefaultGrpFile();
124
    else
125
        return g_grpNamePtr;
126
}
2796 helixhorne 127
const char *G_DefFile(void)
2726 hendricks2 128
{
129
    if (g_defNamePtr == NULL)
130
        return G_DefaultDefFile();
131
    else
132
        return g_defNamePtr;
133
}
2796 helixhorne 134
const char *G_ConFile(void)
2726 hendricks2 135
{
136
    if (g_scriptNamePtr == NULL)
137
        return G_DefaultConFile();
138
    else
139
        return g_scriptNamePtr;
140
}
141
 
142
//////////
143
 
3220 hendricks2 144
void G_MultiPskyInit(void)
145
{
146
    int32_t i;
147
 
148
    // new-style multi-psky handling
149
    pskymultilist[0] = MOONSKY1;
150
    pskymultilist[1] = BIGORBIT1;
151
    pskymultilist[2] = LA;
152
 
153
    pskymultiyscale[0] = 32768;
154
    pskymultiyscale[1] = 32768;
155
    pskymultiyscale[2] = 16384+1024;
156
 
157
    for (i=0; i<3; ++i)
158
    {
159
        pskymultibits[i] = 3;
160
        Bmemset(pskymultioff[i], 0, sizeof(pskymultioff[i]));
161
    }
162
 
163
    // KEEPINSYNC with Polymer MAX OFFSET = 4
164
 
165
    // MOONSKY1
166
    //        earth          mountain   mountain         sun
167
    pskymultioff[0][6]=1;
168
    pskymultioff[0][1]=2;
169
    pskymultioff[0][4]=2;
170
    pskymultioff[0][2]=3;
171
 
172
    // BIGORBIT1   // orbit
173
    //       earth1         2           3           moon/sun
174
    pskymultioff[1][5]=1;
175
    pskymultioff[1][6]=2;
176
    pskymultioff[1][7]=3;
177
    pskymultioff[1][2]=4;
178
 
179
    // LA // la city
180
    //       earth1         2           3           moon/sun
181
    pskymultioff[2][0]=1;
182
    pskymultioff[2][1]=2;
183
    pskymultioff[2][2]=1;
184
    pskymultioff[2][3]=3;
185
    pskymultioff[2][4]=4;
186
    pskymultioff[2][5]=0;
187
    pskymultioff[2][6]=2;
188
    pskymultioff[2][7]=3;
189
 
190
    pskynummultis = 3;
191
 
192
    // default in game:
193
    parallaxyscale = 32768;
194
}
195
 
196
//////////
197
 
2542 helixhorne 198
struct strllist *CommandPaths, *CommandGrps;
199
 
200
void G_AddGroup(const char *buffer)
201
{
202
    char buf[BMAX_PATH];
203
 
3176 helixhorne 204
    struct strllist *s = (struct strllist *)Bcalloc(1,sizeof(struct strllist));
2542 helixhorne 205
 
206
    Bstrcpy(buf, buffer);
207
 
208
    if (Bstrchr(buf,'.') == 0)
209
        Bstrcat(buf,".grp");
210
 
211
    s->str = Bstrdup(buf);
212
 
213
    if (CommandGrps)
214
    {
215
        struct strllist *t;
216
        for (t = CommandGrps; t->next; t=t->next) ;
217
        t->next = s;
218
        return;
219
    }
220
    CommandGrps = s;
221
}
222
 
223
void G_AddPath(const char *buffer)
224
{
3176 helixhorne 225
    struct strllist *s = (struct strllist *)Bcalloc(1,sizeof(struct strllist));
2542 helixhorne 226
    s->str = Bstrdup(buffer);
227
 
228
    if (CommandPaths)
229
    {
230
        struct strllist *t;
231
        for (t = CommandPaths; t->next; t=t->next) ;
232
        t->next = s;
233
        return;
234
    }
235
    CommandPaths = s;
236
}
2549 helixhorne 237
 
238
//////////
239
 
240
int32_t getatoken(scriptfile *sf, const tokenlist *tl, int32_t ntokens)
241
{
242
    char *tok;
243
    int32_t i;
244
 
245
    if (!sf) return T_ERROR;
246
    tok = scriptfile_gettoken(sf);
247
    if (!tok) return T_EOF;
248
 
249
    for (i=ntokens-1; i>=0; i--)
250
    {
251
        if (!Bstrcasecmp(tok, tl[i].text))
252
            return tl[i].tokenid;
253
    }
254
    return T_ERROR;
255
}
2554 helixhorne 256
 
257
//////////
258
 
2752 helixhorne 259
// returns: 1 if file could be opened, 0 else
260
int32_t testkopen(const char *filename, char searchfirst)
261
{
262
    int32_t fd = kopen4load(filename, searchfirst);
263
    if (fd >= 0)
264
        kclose(fd);
265
    return (fd >= 0);
266
}
267
 
2554 helixhorne 268
// checks from path and in ZIPs, returns 1 if NOT found
269
int32_t check_file_exist(const char *fn)
270
{
271
    int32_t opsm = pathsearchmode;
272
    char *tfn;
273
 
274
    pathsearchmode = 1;
275
    if (findfrompath(fn,&tfn) < 0)
276
    {
277
        char buf[BMAX_PATH];
278
 
279
        Bstrcpy(buf,fn);
280
        kzfindfilestart(buf);
281
        if (!kzfindfile(buf))
282
        {
283
            initprintf("Error: file \"%s\" does not exist\n",fn);
284
            pathsearchmode = opsm;
285
            return 1;
286
        }
287
    }
288
    else Bfree(tfn);
289
    pathsearchmode = opsm;
290
 
291
    return 0;
292
}
2555 helixhorne 293
 
294
 
295
//// FILE NAME / DIRECTORY LISTS ////
296
void fnlist_clearnames(fnlist_t *fnl)
297
{
298
    klistfree(fnl->finddirs);
299
    klistfree(fnl->findfiles);
300
 
301
    fnl->finddirs = fnl->findfiles = NULL;
302
    fnl->numfiles = fnl->numdirs = 0;
303
}
304
 
305
// dirflags, fileflags:
306
//  -1 means "don't get dirs/files",
307
//  otherwise ORed to flags for respective klistpath
308
int32_t fnlist_getnames(fnlist_t *fnl, const char *dirname, const char *pattern,
309
                        int32_t dirflags, int32_t fileflags)
310
{
311
    CACHE1D_FIND_REC *r;
312
 
313
    fnlist_clearnames(fnl);
314
 
315
    if (dirflags != -1)
316
        fnl->finddirs = klistpath(dirname, "*", CACHE1D_FIND_DIR|dirflags);
317
    if (fileflags != -1)
318
        fnl->findfiles = klistpath(dirname, pattern, CACHE1D_FIND_FILE|fileflags);
319
 
320
    for (r=fnl->finddirs; r; r=r->next)
321
        fnl->numdirs++;
322
    for (r=fnl->findfiles; r; r=r->next)
323
        fnl->numfiles++;
324
 
325
    return(0);
326
}
327
 
328
 
3269 terminx 329
// loads all group (grp, zip, pk3/4) files in the given directory
2555 helixhorne 330
void G_LoadGroupsInDir(const char *dirname)
331
{
3269 terminx 332
    static const char *extensions[4] = { "*.grp", "*.zip", "*.pk3", "*.pk4" };
2555 helixhorne 333
 
334
    char buf[BMAX_PATH];
335
    int32_t i;
336
 
337
    fnlist_t fnlist = FNLIST_INITIALIZER;
338
 
3269 terminx 339
    for (i=0; i<4; i++)
2555 helixhorne 340
    {
341
        CACHE1D_FIND_REC *rec;
342
 
343
        fnlist_getnames(&fnlist, dirname, extensions[i], -1, 0);
344
 
345
        for (rec=fnlist.findfiles; rec; rec=rec->next)
346
        {
347
            Bsnprintf(buf, sizeof(buf), "%s/%s", dirname, rec->name);
348
            initprintf("Using group file \"%s\".\n", buf);
349
            initgroupfile(buf);
350
        }
351
 
352
        fnlist_clearnames(&fnlist);
353
    }
354
}
355
 
356
void G_DoAutoload(const char *dirname)
357
{
358
    char buf[BMAX_PATH];
359
 
360
    Bsnprintf(buf, sizeof(buf), "autoload/%s", dirname);
361
    G_LoadGroupsInDir(buf);
362
}
2560 helixhorne 363
 
364
////
365
 
366
// returns a buffer of size BMAX_PATH
367
char *dup_filename(const char *fn)
368
{
3176 helixhorne 369
    char *buf = (char *)Bmalloc(BMAX_PATH);
2560 helixhorne 370
 
371
    return Bstrncpyz(buf, fn, BMAX_PATH);
372
}
3004 helixhorne 373
 
374
 
375
// Copy FN to WBUF and append an extension if it's not there, which is checked
376
// case-insensitively.
377
// Returns: 1 if not all characters could be written to WBUF, 0 else.
378
int32_t maybe_append_ext(char *wbuf, int32_t wbufsiz, const char *fn, const char *ext)
379
{
380
    const int32_t slen=Bstrlen(fn), extslen=Bstrlen(ext);
381
    const int32_t haveext = (slen>=extslen && Bstrcasecmp(&fn[slen-extslen], ext)==0);
382
 
383
    Bassert((intptr_t)wbuf != (intptr_t)fn);  // no aliasing
384
 
385
    // If 'fn' has no extension suffixed, append one.
386
    return (Bsnprintf(wbuf, wbufsiz, "%s%s", fn, haveext ? "" : ext) >= wbufsiz);
387
}
3243 helixhorne 388
 
389
 
390
// Approximations to the 2D and 3D euclidean distances. Initial EDuke32 SVN import says
391
// in jmact/mathutil.c: "Ken's reverse-engineering job".
392
// Note that jmact/mathutil.c contains practically the same code, but where the
393
// individual x/y(/z) distances are passed instead.
394
int32_t ldist(const spritetype *s1, const spritetype *s2)
395
{
396
    int32_t x = klabs(s1->x-s2->x);
397
    int32_t y = klabs(s1->y-s2->y);
398
 
399
    if (x<y) swaplong(&x,&y);
400
 
401
    {
402
        int32_t t = y + (y>>1);
403
        return (x - (x>>5) - (x>>7)  + (t>>2) + (t>>6));
404
    }
405
}
406
 
407
int32_t dist(const spritetype *s1, const spritetype *s2)
408
{
409
    int32_t x = klabs(s1->x-s2->x);
410
    int32_t y = klabs(s1->y-s2->y);
411
    int32_t z = klabs((s1->z-s2->z)>>4);
412
 
413
    if (x<y) swaplong(&x,&y);
414
    if (x<z) swaplong(&x,&z);
415
 
416
    {
417
        int32_t t = y + z;
418
        return (x - (x>>4) + (t>>2) + (t>>3));
419
    }
420
}