Subversion Repositories eduke32

Rev

Rev 4559 | Rev 4584 | 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"
4559 hendricks2 7
 
4557 hendricks2 8
#include "grpscan.h"
2542 helixhorne 9
 
3581 hendricks2 10
#ifdef _WIN32
11
# include "winbits.h"
3671 hendricks2 12
# include <shlwapi.h>
13
# include <winnt.h>
14
# ifndef KEY_WOW64_32KEY
15
#  define KEY_WOW64_32KEY 0x0200
16
# endif
3581 hendricks2 17
#endif
18
 
2542 helixhorne 19
#include "common.h"
2726 hendricks2 20
#include "common_game.h"
2542 helixhorne 21
 
2789 hendricks2 22
int32_t g_gameType = GAMEFLAG_DUKE;
2542 helixhorne 23
 
4557 hendricks2 24
int32_t g_dependencyCRC = 0;
25
int32_t g_usingAddon = 0;
26
 
27
// g_gameNamePtr can point to one of: grpfiles[].name (string literal), string
28
// literal, malloc'd block (XXX: possible leak)
29
const char *g_gameNamePtr = NULL;
30
 
4559 hendricks2 31
// grp/con handling
2726 hendricks2 32
 
2796 helixhorne 33
const char *defaultgamegrp[GAMECOUNT] = { "DUKE3D.GRP", "NAM.GRP", "NAPALM.GRP", "WW2GI.GRP" };
34
const char *defaultdeffilename[GAMECOUNT] = { "duke3d.def", "nam.def", "napalm.def", "ww2gi.def" };
35
const char *defaultconfilename = "GAME.CON";
36
const char *defaultgameconfilename[GAMECOUNT] = { "EDUKE.CON", "NAM.CON", "NAPALM.CON", "WW2GI.CON" };
2726 hendricks2 37
 
38
// g_grpNamePtr can ONLY point to a malloc'd block (length BMAX_PATH)
39
char *g_grpNamePtr = NULL;
40
// g_scriptNamePtr can ONLY point to a malloc'd block (length BMAX_PATH)
41
char *g_scriptNamePtr = NULL;
42
 
43
void clearGrpNamePtr(void)
44
{
45
    if (g_grpNamePtr != NULL)
46
        Bfree(g_grpNamePtr);
47
    // g_grpNamePtr assumed to be assigned to right after
48
}
49
 
50
void clearScriptNamePtr(void)
51
{
52
    if (g_scriptNamePtr != NULL)
53
        Bfree(g_scriptNamePtr);
54
    // g_scriptNamePtr assumed to be assigned to right after
55
}
56
 
2796 helixhorne 57
const char *G_DefaultGrpFile(void)
2726 hendricks2 58
{
59
    if (DUKE)
60
        return defaultgamegrp[GAME_DUKE];
61
    // order is important for the following three because GAMEFLAG_NAM overlaps all
62
    else if (NAPALM)
63
        return defaultgamegrp[GAME_NAPALM];
64
    else if (WW2GI)
65
        return defaultgamegrp[GAME_WW2GI];
66
    else if (NAM)
67
        return defaultgamegrp[GAME_NAM];
68
 
69
    return defaultgamegrp[0];
70
}
2796 helixhorne 71
const char *G_DefaultDefFile(void)
2726 hendricks2 72
{
73
    if (DUKE)
74
        return defaultdeffilename[GAME_DUKE];
75
    else if (WW2GI)
76
        return defaultdeffilename[GAME_WW2GI];
77
    else if (NAPALM)
78
    {
2752 helixhorne 79
        if (!testkopen(defaultdeffilename[GAME_NAPALM],0) && testkopen(defaultdeffilename[GAME_NAM],0))
3618 hendricks2 80
            return defaultdeffilename[GAME_NAM]; // NAM/NAPALM Sharing
2726 hendricks2 81
        else
82
            return defaultdeffilename[GAME_NAPALM];
83
    }
84
    else if (NAM)
85
    {
2752 helixhorne 86
        if (!testkopen(defaultdeffilename[GAME_NAM],0) && testkopen(defaultdeffilename[GAME_NAPALM],0))
3618 hendricks2 87
            return defaultdeffilename[GAME_NAPALM]; // NAM/NAPALM Sharing
2726 hendricks2 88
        else
89
            return defaultdeffilename[GAME_NAM];
90
    }
91
 
92
    return defaultdeffilename[0];
93
}
2796 helixhorne 94
const char *G_DefaultConFile(void)
2726 hendricks2 95
{
2752 helixhorne 96
    if (DUKE && testkopen(defaultgameconfilename[GAME_DUKE],0))
2726 hendricks2 97
        return defaultgameconfilename[GAME_DUKE];
2752 helixhorne 98
    else if (WW2GI && testkopen(defaultgameconfilename[GAME_WW2GI],0))
2726 hendricks2 99
        return defaultgameconfilename[GAME_WW2GI];
100
    else if (NAPALM)
101
    {
2752 helixhorne 102
        if (!testkopen(defaultgameconfilename[GAME_NAPALM],0))
2726 hendricks2 103
        {
2752 helixhorne 104
            if (testkopen(defaultgameconfilename[GAME_NAM],0))
3618 hendricks2 105
                return defaultgameconfilename[GAME_NAM]; // NAM/NAPALM Sharing
2726 hendricks2 106
        }
107
        else
108
            return defaultgameconfilename[GAME_NAPALM];
109
    }
110
    else if (NAM)
111
    {
2752 helixhorne 112
        if (!testkopen(defaultgameconfilename[GAME_NAM],0))
2726 hendricks2 113
        {
2752 helixhorne 114
            if (testkopen(defaultgameconfilename[GAME_NAPALM],0))
3618 hendricks2 115
                return defaultgameconfilename[GAME_NAPALM]; // NAM/NAPALM Sharing
2726 hendricks2 116
        }
117
        else
118
            return defaultgameconfilename[GAME_NAM];
119
    }
120
 
121
    return defaultconfilename;
122
}
123
 
2796 helixhorne 124
const char *G_GrpFile(void)
2726 hendricks2 125
{
126
    if (g_grpNamePtr == NULL)
127
        return G_DefaultGrpFile();
128
    else
129
        return g_grpNamePtr;
130
}
3654 terminx 131
 
2796 helixhorne 132
const char *G_DefFile(void)
2726 hendricks2 133
{
134
    if (g_defNamePtr == NULL)
135
        return G_DefaultDefFile();
136
    else
137
        return g_defNamePtr;
138
}
3654 terminx 139
 
2796 helixhorne 140
const char *G_ConFile(void)
2726 hendricks2 141
{
142
    if (g_scriptNamePtr == NULL)
143
        return G_DefaultConFile();
144
    else
145
        return g_scriptNamePtr;
146
}
147
 
148
//////////
149
 
3976 helixhorne 150
#define NUMPSKYMULTIS 5
151
EDUKE32_STATIC_ASSERT(NUMPSKYMULTIS <= MAXPSKYMULTIS);
152
EDUKE32_STATIC_ASSERT(PSKYOFF_MAX <= MAXPSKYTILES);
153
 
3975 helixhorne 154
// Set up new-style multi-psky handling.
3976 helixhorne 155
void G_InitMultiPsky(int32_t CLOUDYOCEAN__DYN, int32_t MOONSKY1__DYN, int32_t BIGORBIT1__DYN, int32_t LA__DYN)
3220 hendricks2 156
{
157
    int32_t i;
158
 
3976 helixhorne 159
    psky_t *defaultsky = &multipsky[0];
160
    psky_t *oceansky = &multipsky[1];
161
    psky_t *moonsky = &multipsky[2];
162
    psky_t *spacesky = &multipsky[3];
163
    psky_t *citysky = &multipsky[4];
3220 hendricks2 164
 
3975 helixhorne 165
    static int32_t inited;
166
    if (inited)
167
        return;
168
    inited = 1;
3220 hendricks2 169
 
3976 helixhorne 170
    multipskytile[0] = -1;
171
    multipskytile[1] = CLOUDYOCEAN__DYN;
172
    multipskytile[2] = MOONSKY1__DYN;
173
    multipskytile[3] = BIGORBIT1__DYN;
174
    multipskytile[4] = LA__DYN;
3220 hendricks2 175
 
3976 helixhorne 176
    pskynummultis = NUMPSKYMULTIS;
3220 hendricks2 177
 
3975 helixhorne 178
    // When adding other multi-skies, take care that the tileofs[] values are
179
    // <= PSKYOFF_MAX. (It can be increased up to MAXPSKYTILES, but should be
180
    // set as tight as possible.)
181
 
3976 helixhorne 182
    // The default sky properties (all others are implicitly zero):
183
    defaultsky->lognumtiles = 3;
184
    defaultsky->horizfrac = 32768;
185
 
186
    // CLOUDYOCEAN
187
    // Aligns with the drawn scene horizon because it has one itself.
188
    oceansky->lognumtiles = 3;
189
    oceansky->horizfrac = 65536;
190
 
3220 hendricks2 191
    // MOONSKY1
192
    //        earth          mountain   mountain         sun
3975 helixhorne 193
    moonsky->lognumtiles = 3;
194
    moonsky->horizfrac = 32768;
195
    moonsky->tileofs[6] = 1;
196
    moonsky->tileofs[1] = 2;
197
    moonsky->tileofs[4] = 2;
198
    moonsky->tileofs[2] = 3;
3220 hendricks2 199
 
200
    // BIGORBIT1   // orbit
201
    //       earth1         2           3           moon/sun
3975 helixhorne 202
    spacesky->lognumtiles = 3;
203
    spacesky->horizfrac = 32768;
204
    spacesky->tileofs[5] = 1;
205
    spacesky->tileofs[6] = 2;
206
    spacesky->tileofs[7] = 3;
207
    spacesky->tileofs[2] = 4;
3220 hendricks2 208
 
209
    // LA // la city
210
    //       earth1         2           3           moon/sun
3975 helixhorne 211
    citysky->lognumtiles = 3;
212
    citysky->horizfrac = 16384+1024;
213
    citysky->tileofs[0] = 1;
214
    citysky->tileofs[1] = 2;
215
    citysky->tileofs[2] = 1;
216
    citysky->tileofs[3] = 3;
217
    citysky->tileofs[4] = 4;
218
    citysky->tileofs[5] = 0;
219
    citysky->tileofs[6] = 2;
220
    citysky->tileofs[7] = 3;
3220 hendricks2 221
 
3975 helixhorne 222
    for (i=0; i<pskynummultis; ++i)
223
    {
224
        int32_t j;
225
        for (j=0; j<(1<<multipsky[i].lognumtiles); ++j)
226
            Bassert(multipsky[i].tileofs[j] <= PSKYOFF_MAX);
227
    }
3976 helixhorne 228
}
3220 hendricks2 229
 
3976 helixhorne 230
void G_SetupGlobalPsky(void)
231
{
232
    int32_t i, mskyidx=0;
233
 
234
    // NOTE: Loop must be running backwards for the same behavior as the game
235
    // (greatest sector index with matching parallaxed sky takes precedence).
236
    for (i=numsectors-1; i>=0; i--)
237
    {
238
        if (sector[i].ceilingstat & 1)
239
        {
4006 helixhorne 240
            mskyidx = getpskyidx(sector[i].ceilingpicnum);
3976 helixhorne 241
            if (mskyidx > 0)
242
                break;
243
        }
244
    }
245
 
246
    g_pskyidx = mskyidx;
3220 hendricks2 247
}
248
 
249
//////////
250
 
4557 hendricks2 251
static char g_rootDir[BMAX_PATH];
252
char g_modDir[BMAX_PATH] = "/";
253
 
254
int32_t kopen4loadfrommod(const char *filename, char searchfirst)
255
{
256
    int32_t r=-1;
257
 
258
    if (g_modDir[0]!='/' || g_modDir[1]!=0)
259
    {
260
        static char fn[BMAX_PATH];
261
 
262
        Bsnprintf(fn, sizeof(fn), "%s/%s",g_modDir,filename);
263
        r = kopen4load(fn,searchfirst);
264
    }
265
 
266
    if (r < 0)
267
        r = kopen4load(filename,searchfirst);
268
 
269
    return r;
270
}
271
 
272
int32_t usecwd;
273
static void G_LoadAddon(void);
274
int32_t g_groupFileHandle;
275
 
276
void G_ExtPreInit(int32_t argc,const char **argv)
277
{
278
    usecwd = G_CheckCmdSwitch(argc, argv, "-usecwd");
279
 
280
#ifdef _WIN32
281
    GetModuleFileName(NULL,g_rootDir,BMAX_PATH);
282
    Bcorrectfilename(g_rootDir,1);
283
    //chdir(g_rootDir);
284
#else
285
    getcwd(g_rootDir,BMAX_PATH);
286
    strcat(g_rootDir,"/");
3582 hendricks2 287
#endif
4557 hendricks2 288
}
3582 hendricks2 289
 
4557 hendricks2 290
void G_ExtInit(void)
3582 hendricks2 291
{
4557 hendricks2 292
    char cwd[BMAX_PATH];
293
 
294
    if (getcwd(cwd,BMAX_PATH))
295
    {
296
#if defined(__APPLE__)
297
        /* Dirty hack on OS X to also look for gamedata inside the application bundle - rhoenie 08/08 */
298
        char seekinappcontainer[BMAX_PATH];
299
        Bsnprintf(seekinappcontainer,sizeof(seekinappcontainer),"%s/EDuke32.app/", cwd);
300
        addsearchpath(seekinappcontainer);
3582 hendricks2 301
#endif
4557 hendricks2 302
        addsearchpath(cwd);
303
    }
304
 
305
    if (CommandPaths)
306
    {
307
        int32_t i;
308
        struct strllist *s;
309
        while (CommandPaths)
310
        {
311
            s = CommandPaths->next;
312
            i = addsearchpath(CommandPaths->str);
313
            if (i < 0)
314
            {
315
                initprintf("Failed adding %s for game data: %s\n", CommandPaths->str,
316
                           i==-1 ? "not a directory" : "no such directory");
317
            }
318
 
319
            Bfree(CommandPaths->str);
320
            Bfree(CommandPaths);
321
            CommandPaths = s;
322
        }
323
    }
324
 
325
#if defined(_WIN32)
326
    if (!access("user_profiles_enabled", F_OK))
327
#else
328
    if (usecwd == 0 && access("user_profiles_disabled", F_OK))
329
#endif
330
    {
331
        char *homedir;
332
        int32_t asperr;
333
 
334
        if ((homedir = Bgethomedir()))
335
        {
336
            Bsnprintf(cwd,sizeof(cwd),"%s/"
337
#if defined(_WIN32)
338
                      "EDuke32 Settings"
339
#elif defined(__APPLE__)
340
                      "Library/Application Support/EDuke32"
341
#elif defined(GEKKO)
342
                      "apps/eduke32"
343
#else
344
                      ".eduke32"
345
#endif
346
                      ,homedir);
347
            asperr = addsearchpath(cwd);
348
            if (asperr == -2)
349
            {
350
                if (Bmkdir(cwd,S_IRWXU) == 0) asperr = addsearchpath(cwd);
351
                else asperr = -1;
352
            }
353
            if (asperr == 0)
354
                chdir(cwd);
355
            Bfree(homedir);
356
        }
357
    }
358
 
359
    // JBF 20031220: Because it's annoying renaming GRP files whenever I want to test different game data
360
    if (g_grpNamePtr == NULL)
361
    {
362
        const char *cp = getenv("DUKE3DGRP");
363
        if (cp)
364
        {
365
            clearGrpNamePtr();
366
            g_grpNamePtr = dup_filename(cp);
367
            initprintf("Using \"%s\" as main GRP file\n", g_grpNamePtr);
368
        }
369
    }
3582 hendricks2 370
}
371
 
4557 hendricks2 372
void G_ExtPreStartupWindow(void)
373
{
374
    ScanGroups();
375
    {
376
        // try and identify the 'defaultgamegrp' in the set of GRPs.
377
        // if it is found, set up the environment accordingly for the game it represents.
378
        // if it is not found, choose the first GRP from the list
379
        struct grpfile *fg, *first = NULL;
380
 
381
        for (fg = foundgrps; fg; fg=fg->next)
382
        {
383
            struct grpfile *grp;
384
            for (grp = listgrps; grp; grp=grp->next)
385
                if (fg->crcval == grp->crcval) break;
386
 
387
            if (grp == NULL)
388
                continue;
389
 
390
            fg->game = grp->game;
391
            if (!first) first = fg;
392
            if (!Bstrcasecmp(fg->name, G_DefaultGrpFile()))
393
            {
394
                g_gameType = grp->game;
395
                g_gameNamePtr = grp->name;
396
                break;
397
            }
398
        }
399
        if (!fg && first)
400
        {
401
            if (g_grpNamePtr == NULL)
402
            {
403
                clearGrpNamePtr();
404
                g_grpNamePtr = dup_filename(first->name);
405
            }
406
            g_gameType = first->game;
407
            g_gameNamePtr = listgrps->name;
408
        }
409
        else if (!fg) g_gameNamePtr = NULL;
410
    }
411
}
412
 
413
void G_ExtPostStartupWindow(int32_t autoload)
414
{
415
    if (g_modDir[0] != '/')
416
    {
417
        char cwd[BMAX_PATH];
418
 
419
        Bstrcat(g_rootDir,g_modDir);
420
        addsearchpath(g_rootDir);
421
//        addsearchpath(mod_dir);
422
 
423
        if (getcwd(cwd,BMAX_PATH))
424
        {
425
            Bsprintf(cwd,"%s/%s",cwd,g_modDir);
426
            if (!Bstrcmp(g_rootDir, cwd))
427
            {
428
                if (addsearchpath(cwd) == -2)
429
                    if (Bmkdir(cwd,S_IRWXU) == 0) addsearchpath(cwd);
430
            }
431
        }
432
 
433
#ifdef USE_OPENGL
434
        Bsprintf(cwd,"%s/%s",g_modDir,TEXCACHEFILE);
435
        Bstrcpy(TEXCACHEFILE,cwd);
436
#endif
437
    }
438
 
439
    if (g_usingAddon)
440
        G_LoadAddon();
441
 
442
    {
443
        int32_t i;
444
        const char *grpfile = G_GrpFile();
445
 
446
        if (g_dependencyCRC)
447
        {
448
            struct grpfile * grp = FindGroup(g_dependencyCRC);
449
            if (grp)
450
            {
451
                if ((i = initgroupfile(grp->name)) == -1)
452
                    initprintf("Warning: could not find main data file \"%s\"!\n",grp->name);
453
                else
454
                    initprintf("Using \"%s\" as main game data file.\n", grp->name);
455
            }
456
        }
457
 
458
        if ((i = initgroupfile(grpfile)) == -1)
459
            initprintf("Warning: could not find main data file \"%s\"!\n",grpfile);
460
        else
461
            initprintf("Using \"%s\" as main game data file.\n", grpfile);
462
 
463
        if (autoload)
464
        {
465
            G_LoadGroupsInDir("autoload");
466
 
467
            if (i != -1)
468
                G_DoAutoload(grpfile);
469
        }
470
    }
471
 
472
    if (g_modDir[0] != '/')
473
        G_LoadGroupsInDir(g_modDir);
474
 
475
    if (g_defNamePtr == NULL)
476
    {
477
        const char *tmpptr = getenv("DUKE3DDEF");
478
        if (tmpptr)
479
        {
480
            clearDefNamePtr();
481
            g_defNamePtr = dup_filename(tmpptr);
482
            initprintf("Using \"%s\" as definitions file\n", g_defNamePtr);
483
        }
484
    }
485
 
486
    loaddefinitions_game(G_DefFile(), TRUE);
487
 
488
    {
489
        struct strllist *s;
490
 
491
        pathsearchmode = 1;
492
        while (CommandGrps)
493
        {
494
            int32_t j;
495
 
496
            s = CommandGrps->next;
497
 
498
            if ((j = initgroupfile(CommandGrps->str)) == -1)
499
                initprintf("Could not find file \"%s\".\n",CommandGrps->str);
500
            else
501
            {
502
                g_groupFileHandle = j;
503
                initprintf("Using file \"%s\" as game data.\n",CommandGrps->str);
504
                if (autoload)
505
                    G_DoAutoload(CommandGrps->str);
506
            }
507
 
508
            Bfree(CommandGrps->str);
509
            Bfree(CommandGrps);
510
            CommandGrps = s;
511
        }
512
        pathsearchmode = 0;
513
    }
514
}
515
 
3622 terminx 516
#ifdef _WIN32
3637 terminx 517
const char * G_GetInstallPath(int32_t insttype)
3622 terminx 518
{
3637 terminx 519
    static char spath[NUMINSTPATHS][BMAX_PATH];
520
    static int32_t success[NUMINSTPATHS] = { -1, -1 };
3622 terminx 521
    int32_t siz = BMAX_PATH;
522
 
3637 terminx 523
    if (success[insttype] == -1)
524
    {
3671 hendricks2 525
        HKEY HKLM32;
526
        LONG keygood = RegOpenKeyEx(HKEY_LOCAL_MACHINE, NULL, 0, KEY_READ | KEY_WOW64_32KEY, &HKLM32);
527
        // KEY_WOW64_32KEY gets us around Wow6432Node on 64-bit builds
528
 
529
        if (keygood == ERROR_SUCCESS)
4127 hendricks2 530
        {
3671 hendricks2 531
            switch (insttype)
532
            {
533
            case INSTPATH_STEAM:
534
                success[insttype] = SHGetValueA(HKLM32, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App 225140", "InstallLocation", NULL, spath[insttype], (LPDWORD)&siz);
535
                break;
536
            case INSTPATH_GOG:
537
                success[insttype] = SHGetValueA(HKLM32, "SOFTWARE\\GOG.com\\GOGDUKE3D", "PATH", NULL, spath[insttype], (LPDWORD)&siz);
538
                break;
539
            }
4127 hendricks2 540
 
541
            RegCloseKey(HKLM32);
542
        }
3637 terminx 543
    }
3622 terminx 544
 
3637 terminx 545
    if (success[insttype] == ERROR_SUCCESS)
546
        return spath[insttype];
3622 terminx 547
 
548
    return NULL;
549
}
550
#endif
551
 
4557 hendricks2 552
static void G_LoadAddon(void)
553
{
554
    struct grpfile * grp;
555
    int32_t crc = 0;  // compiler-happy
556
 
557
    switch (g_usingAddon)
558
    {
559
    case ADDON_DUKEDC:
560
        crc = DUKEDC_CRC;
561
        break;
562
    case ADDON_NWINTER:
563
        crc = DUKENW_CRC;
564
        break;
565
    case ADDON_CARIBBEAN:
566
        crc = DUKECB_CRC;
567
        break;
568
    }
569
 
570
    if (!crc) return;
571
 
572
    grp = FindGroup(crc);
573
 
574
    if (grp && FindGroup(DUKE15_CRC))
575
    {
576
        clearGrpNamePtr();
577
        g_grpNamePtr = dup_filename(FindGroup(DUKE15_CRC)->name);
578
 
579
        G_AddGroup(grp->name);
580
 
581
        for (grp = listgrps; grp; grp=grp->next)
582
            if (crc == grp->crcval) break;
583
 
584
        if (grp != NULL && grp->scriptname)
585
        {
586
            clearScriptNamePtr();
587
            g_scriptNamePtr = dup_filename(grp->scriptname);
588
        }
589
 
590
        if (grp != NULL && grp->defname)
591
        {
592
            clearDefNamePtr();
593
            g_defNamePtr = dup_filename(grp->defname);
594
        }
595
    }
596
}
597
 
3581 hendricks2 598
void G_AddSearchPaths(void)
599
{
600
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
601
    addsearchpath("/usr/share/games/jfduke3d");
602
    addsearchpath("/usr/local/share/games/jfduke3d");
603
    addsearchpath("/usr/share/games/eduke32");
604
    addsearchpath("/usr/local/share/games/eduke32");
605
#elif defined(__APPLE__)
606
    addsearchpath("/Library/Application Support/JFDuke3D");
607
    addsearchpath("/Library/Application Support/EDuke32");
608
#elif defined (_WIN32)
3615 terminx 609
    // detect Steam and GOG versions of Duke3D
610
    char buf[BMAX_PATH];
3671 hendricks2 611
    const char* instpath;
3615 terminx 612
 
3671 hendricks2 613
    if ((instpath = G_GetInstallPath(INSTPATH_STEAM)))
3622 terminx 614
    {
4557 hendricks2 615
        Bsnprintf(buf, sizeof(buf), "%s/gameroot", instpath);
3622 terminx 616
        addsearchpath(buf);
3615 terminx 617
 
4557 hendricks2 618
        Bsnprintf(buf, sizeof(buf), "%s/gameroot/addons", instpath);
3622 terminx 619
        addsearchpath(buf);
3615 terminx 620
    }
621
 
3671 hendricks2 622
    if ((instpath = G_GetInstallPath(INSTPATH_GOG)))
623
        addsearchpath(instpath);
3581 hendricks2 624
#endif
625
}
626
 
3654 terminx 627
void G_CleanupSearchPaths(void)
628
{
629
#ifdef _WIN32
630
    char buf[BMAX_PATH];
3671 hendricks2 631
    const char* instpath;
3654 terminx 632
 
3671 hendricks2 633
    if ((instpath = G_GetInstallPath(INSTPATH_STEAM)))
3654 terminx 634
    {
4557 hendricks2 635
        Bsnprintf(buf, sizeof(buf), "%s/gameroot", instpath);
3654 terminx 636
        removesearchpath(buf);
637
 
4557 hendricks2 638
        Bsnprintf(buf, sizeof(buf), "%s/gameroot/addons", instpath);
3654 terminx 639
        removesearchpath(buf);
640
    }
641
 
3671 hendricks2 642
    if ((instpath = G_GetInstallPath(INSTPATH_GOG)))
643
        removesearchpath(instpath);
3654 terminx 644
#endif
645
}
646
 
3581 hendricks2 647
//////////
648
 
2542 helixhorne 649
struct strllist *CommandPaths, *CommandGrps;
650
 
4128 hendricks2 651
char **g_scriptModules = NULL;
652
int32_t g_scriptModulesNum = 0;
653
 
2542 helixhorne 654
void G_AddGroup(const char *buffer)
655
{
656
    char buf[BMAX_PATH];
657
 
4491 helixhorne 658
    struct strllist *s = (struct strllist *)Xcalloc(1,sizeof(struct strllist));
2542 helixhorne 659
 
660
    Bstrcpy(buf, buffer);
661
 
662
    if (Bstrchr(buf,'.') == 0)
663
        Bstrcat(buf,".grp");
664
 
4491 helixhorne 665
    s->str = Xstrdup(buf);
2542 helixhorne 666
 
667
    if (CommandGrps)
668
    {
669
        struct strllist *t;
670
        for (t = CommandGrps; t->next; t=t->next) ;
671
        t->next = s;
672
        return;
673
    }
674
    CommandGrps = s;
675
}
676
 
677
void G_AddPath(const char *buffer)
678
{
4491 helixhorne 679
    struct strllist *s = (struct strllist *)Xcalloc(1,sizeof(struct strllist));
680
    s->str = Xstrdup(buffer);
2542 helixhorne 681
 
682
    if (CommandPaths)
683
    {
684
        struct strllist *t;
685
        for (t = CommandPaths; t->next; t=t->next) ;
686
        t->next = s;
687
        return;
688
    }
689
    CommandPaths = s;
690
}
2549 helixhorne 691
 
4128 hendricks2 692
void G_AddCon(const char *buffer)
693
{
694
    clearScriptNamePtr();
695
    g_scriptNamePtr = dup_filename(buffer);
696
    initprintf("Using CON file \"%s\".\n",g_scriptNamePtr);
697
}
698
 
699
void G_AddConModule(const char *buffer)
700
{
4491 helixhorne 701
    g_scriptModules = (char **) Xrealloc (g_scriptModules, (g_scriptModulesNum+1) * sizeof(char *));
702
    g_scriptModules[g_scriptModulesNum] = Xstrdup(buffer);
4128 hendricks2 703
    ++g_scriptModulesNum;
704
}
705
 
2549 helixhorne 706
//////////
707
 
3269 terminx 708
// loads all group (grp, zip, pk3/4) files in the given directory
2555 helixhorne 709
void G_LoadGroupsInDir(const char *dirname)
710
{
3269 terminx 711
    static const char *extensions[4] = { "*.grp", "*.zip", "*.pk3", "*.pk4" };
2555 helixhorne 712
 
713
    char buf[BMAX_PATH];
714
    int32_t i;
715
 
716
    fnlist_t fnlist = FNLIST_INITIALIZER;
717
 
3269 terminx 718
    for (i=0; i<4; i++)
2555 helixhorne 719
    {
720
        CACHE1D_FIND_REC *rec;
721
 
722
        fnlist_getnames(&fnlist, dirname, extensions[i], -1, 0);
723
 
724
        for (rec=fnlist.findfiles; rec; rec=rec->next)
725
        {
726
            Bsnprintf(buf, sizeof(buf), "%s/%s", dirname, rec->name);
727
            initprintf("Using group file \"%s\".\n", buf);
728
            initgroupfile(buf);
729
        }
730
 
731
        fnlist_clearnames(&fnlist);
732
    }
733
}
734
 
735
void G_DoAutoload(const char *dirname)
736
{
737
    char buf[BMAX_PATH];
738
 
739
    Bsnprintf(buf, sizeof(buf), "autoload/%s", dirname);
740
    G_LoadGroupsInDir(buf);
741
}
4564 hendricks2 742
 
743
//////////
744
 
745
static uint8_t water_pal[768], slime_pal[768], title_pal[768], dre_alms[768], ending_pal[768];
746
 
747
uint8_t *basepaltable[BASEPALCOUNT] = {
748
    palette, water_pal, slime_pal,
749
    dre_alms, title_pal, ending_pal,
750
    NULL /*anim_pal*/
751
};
752
 
753
int32_t g_firstFogPal;
754
 
755
int32_t G_LoadLookups(void)
756
{
757
    int32_t fp, j;
758
 
759
    if ((fp=kopen4loadfrommod("lookup.dat",0)) == -1)
760
    {
761
        if ((fp=kopen4loadfrommod("lookup.dat",1)) == -1)
762
        {
763
            initprintf("ERROR: File \"lookup.dat\" not found.\n");
764
            return 1;
765
        }
766
    }
767
 
768
    j = loadlookups(fp);
769
 
770
    if (j < 0)
771
    {
772
        if (j == -1)
773
            initprintf("ERROR loading \"lookup.dat\": failed reading enough data.\n");
774
        return 1;
775
    }
776
 
777
    for (j=1; j<=5; j++)
778
    {
779
        // Account for TITLE and REALMS swap between basepal number and on-disk order.
780
        // XXX: this reordering is better off as an argument to us.
781
        int32_t basepalnum = (j == 3 || j == 4) ? 4+3-j : j;
782
 
783
        if (kread(fp, basepaltable[basepalnum], 768) != 768)
784
            return -1;
785
    }
786
 
787
    kclose(fp);
788
 
789
    g_firstFogPal = generatefogpals();
790
 
791
    fillemptylookups();
792
 
793
    return 0;
794
}