Subversion Repositories eduke32

Rev

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

Rev Author Line No. Line
1652 terminx 1
//-------------------------------------------------------------------------
2
/*
3
Copyright (C) 2010 EDuke32 developers and contributors
4
 
5
This file is part of EDuke32.
6
 
7
EDuke32 is free software; you can redistribute it and/or
8
modify it under the terms of the GNU General Public License version 2
9
as published by the Free Software Foundation.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
 
15
See the GNU General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
4541 hendricks2 19
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
1652 terminx 20
*/
21
//-------------------------------------------------------------------------
22
 
241 terminx 23
#include "compat.h"
24
#include "baselayer.h"
25
 
26
#include "scriptfile.h"
27
#include "cache1d.h"
28
#include "crc32.h"
29
 
30
#include "duke3d.h"
2726 hendricks2 31
#include "common_game.h"
241 terminx 32
#include "grpscan.h"
33
 
3708 terminx 34
// custom GRP support for the startup window, file format reflects the structure below
35
#define GAMELISTFILE "games.list"
3803 terminx 36
//    name                                     crc          size      flags                         dependency  scriptname     defname
3708 terminx 37
struct grpfile internalgrpfiles[NUMGRPFILES] =
559 terminx 38
{
3803 terminx 39
    { "Duke Nukem 3D",                         DUKE13_CRC,  26524524, GAMEFLAG_DUKE,                         0, NULL,          NULL,        NULL },
40
    { "Duke Nukem 3D (South Korean Censored)", DUKEKR_CRC,  26385383, GAMEFLAG_DUKE,                         0, NULL,          NULL,        NULL },
41
    { "Duke Nukem 3D: Atomic Edition",         DUKE15_CRC,  44356548, GAMEFLAG_DUKE,                         0, NULL,          NULL,        NULL },
42
    { "Duke Nukem 3D: Plutonium Pak",          DUKEPP_CRC,  44348015, GAMEFLAG_DUKE,                         0, NULL,          NULL,        NULL },
43
    { "Duke Nukem 3D Shareware 0.99",          DUKE099_CRC, 9690241,  GAMEFLAG_DUKE|GAMEFLAG_DUKEBETA,       0, NULL,          NULL,        NULL },
44
    { "Duke Nukem 3D Shareware 1.0",           DUKE10_CRC,  10429258, GAMEFLAG_DUKE|GAMEFLAG_SHAREWARE,      0, NULL,          NULL,        NULL },
45
    { "Duke Nukem 3D Shareware 1.1",           DUKE11_CRC,  10442980, GAMEFLAG_DUKE|GAMEFLAG_SHAREWARE,      0, NULL,          NULL,        NULL },
46
    { "Duke Nukem 3D Shareware 1.3D",          DUKESW_CRC,  11035779, GAMEFLAG_DUKE|GAMEFLAG_SHAREWARE,      0, NULL,          NULL,        NULL },
47
    { "Duke Nukem 3D Mac Demo",                DUKEMD_CRC,  10444391, GAMEFLAG_DUKE|GAMEFLAG_SHAREWARE,      0, NULL,          NULL,        NULL },
48
    { "Duke it out in D.C.",                   DUKEDC_CRC,  8410183 , GAMEFLAG_DUKE|GAMEFLAG_ADDON, DUKE15_CRC, NULL,          NULL,        NULL },
49
    { "Duke Caribbean: Life's a Beach",        DUKECB_CRC,  22213819, GAMEFLAG_DUKE|GAMEFLAG_ADDON, DUKE15_CRC, NULL,          NULL,        NULL },
4887 hendricks2 50
    { "Duke: Nuclear Winter",                  DUKENW_CRC,  16169365, GAMEFLAG_DUKE|GAMEFLAG_ADDON|GAMEFLAG_NWINTER, DUKE15_CRC, "NWINTER.CON", NULL,        NULL },
4789 hendricks2 51
    { "NAM",                                   NAM_CRC,     43448927, GAMEFLAG_NAM,                          0, NULL,          NULL,        NULL },
52
    { "NAPALM",                                NAPALM_CRC,  44365728, GAMEFLAG_NAM|GAMEFLAG_NAPALM,          0, NULL,          NULL,        NULL },
53
    { "WWII GI",                               WW2GI_CRC,   77939508, GAMEFLAG_WW2GI|GAMEFLAG_NAM,           0, NULL,          NULL,        NULL },
559 terminx 54
};
241 terminx 55
struct grpfile *foundgrps = NULL;
3708 terminx 56
struct grpfile *listgrps = NULL;
241 terminx 57
 
3708 terminx 58
static void LoadList(const char * filename)
59
{
60
    struct grpfile *fg;
61
 
62
    char *grpend = NULL;
63
 
64
    scriptfile *script = scriptfile_fromfile(filename);
65
 
66
    if (!script)
67
        return;
68
 
69
    scriptfile_addsymbolvalue("GAMEFLAG_DUKE", GAMEFLAG_DUKE);
70
    scriptfile_addsymbolvalue("GAMEFLAG_ADDON", GAMEFLAG_DUKE|GAMEFLAG_ADDON);
5050 hendricks2 71
    scriptfile_addsymbolvalue("GAMEFLAG_NAM", GAMEFLAG_NAM);
72
    scriptfile_addsymbolvalue("GAMEFLAG_NAPALM", GAMEFLAG_NAM|GAMEFLAG_NAPALM);
73
    scriptfile_addsymbolvalue("GAMEFLAG_WW2GI", GAMEFLAG_NAM|GAMEFLAG_WW2GI);
3708 terminx 74
    scriptfile_addsymbolvalue("DUKE15_CRC", DUKE15_CRC);
5050 hendricks2 75
    scriptfile_addsymbolvalue("DUKEPP_CRC", DUKEPP_CRC);
3708 terminx 76
    scriptfile_addsymbolvalue("DUKE13_CRC", DUKE13_CRC);
77
    scriptfile_addsymbolvalue("DUKEDC_CRC", DUKEDC_CRC);
78
    scriptfile_addsymbolvalue("DUKECB_CRC", DUKECB_CRC);
79
    scriptfile_addsymbolvalue("DUKENW_CRC", DUKENW_CRC);
5050 hendricks2 80
    scriptfile_addsymbolvalue("NAM_CRC", NAM_CRC);
81
    scriptfile_addsymbolvalue("NAPALM_CRC", NAPALM_CRC);
82
    scriptfile_addsymbolvalue("WW2GI_CRC", WW2GI_CRC);
3708 terminx 83
 
3711 helixhorne 84
    while (!scriptfile_eof(script))
3708 terminx 85
    {
3711 helixhorne 86
        enum
87
        {
88
            T_GRPINFO,
89
            T_GAMENAME,
90
            T_CRC,
91
            T_SIZE,
92
            T_DEPCRC,
93
            T_SCRIPTNAME,
94
            T_DEFNAME,
95
            T_FLAGS,
96
        };
3708 terminx 97
 
3711 helixhorne 98
        static const tokenlist profiletokens[] =
99
        {
100
            { "grpinfo",            T_GRPINFO },
101
        };
3708 terminx 102
 
4385 terminx 103
        int32_t token = getatoken(script,profiletokens,ARRAY_SIZE(profiletokens));
3708 terminx 104
        switch (token)
105
        {
106
        case T_GRPINFO:
3711 helixhorne 107
        {
108
            int32_t gsize = 0, gcrcval = 0, gflags = GAMEFLAG_DUKE, gdepcrc = DUKE15_CRC;
109
            char *gname = NULL, *gscript = NULL, *gdef = NULL;
110
 
111
            static const tokenlist grpinfotokens[] =
3708 terminx 112
            {
3711 helixhorne 113
                { "name",           T_GAMENAME },
114
                { "scriptname",     T_SCRIPTNAME },
115
                { "defname",        T_DEFNAME },
116
                { "crc",            T_CRC },
117
                { "dependency",     T_DEPCRC },
118
                { "size",           T_SIZE },
119
                { "flags",          T_FLAGS },
3708 terminx 120
 
3711 helixhorne 121
            };
3708 terminx 122
 
3711 helixhorne 123
            if (scriptfile_getbraces(script,&grpend)) break;
3708 terminx 124
 
3711 helixhorne 125
            while (script->textptr < grpend)
126
            {
4385 terminx 127
                int32_t token = getatoken(script,grpinfotokens,ARRAY_SIZE(grpinfotokens));
3708 terminx 128
 
3711 helixhorne 129
                switch (token)
3708 terminx 130
                {
3711 helixhorne 131
                case T_GAMENAME:
132
                    scriptfile_getstring(script,&gname); break;
133
                case T_SCRIPTNAME:
134
                    scriptfile_getstring(script,&gscript); break;
135
                case T_DEFNAME:
136
                    scriptfile_getstring(script,&gdef); break;
3708 terminx 137
 
3711 helixhorne 138
                case T_FLAGS:
5050 hendricks2 139
                    scriptfile_getsymbol(script,&gflags); gflags &= GAMEFLAGMASK; break;
3711 helixhorne 140
                case T_DEPCRC:
141
                    scriptfile_getsymbol(script,&gdepcrc); break;
142
                case T_CRC:
143
                    scriptfile_getsymbol(script,&gcrcval); break;
144
                case T_SIZE:
145
                    scriptfile_getnumber(script,&gsize); break;
146
                default:
147
                    break;
148
                }
3708 terminx 149
 
4491 helixhorne 150
                fg = (struct grpfile *)Xcalloc(1, sizeof(struct grpfile));
3711 helixhorne 151
                fg->next = listgrps;
152
                listgrps = fg;
3708 terminx 153
 
3711 helixhorne 154
                if (gname)
4491 helixhorne 155
                    fg->name = Xstrdup(gname);
3708 terminx 156
 
3711 helixhorne 157
                fg->size = gsize;
158
                fg->crcval = gcrcval;
159
                fg->dependency = gdepcrc;
160
                fg->game = gflags;
3708 terminx 161
 
3711 helixhorne 162
                if (gscript)
163
                    fg->scriptname = dup_filename(gscript);
3708 terminx 164
 
3711 helixhorne 165
                if (gdef)
166
                    fg->defname = dup_filename(gdef);
3708 terminx 167
            }
3711 helixhorne 168
            break;
169
        }
3708 terminx 170
 
171
        default:
172
            break;
173
        }
174
    }
175
 
176
    scriptfile_close(script);
177
    scriptfile_clearsymbols();
178
}
179
 
180
static void LoadGameList(void)
181
{
182
    struct grpfile *fg;
183
    CACHE1D_FIND_REC *srch, *sidx;
184
 
185
    int32_t i;
186
 
187
    for (i = 0; i<NUMGRPFILES; i++)
188
    {
4491 helixhorne 189
        fg = (struct grpfile *)Xcalloc(1, sizeof(struct grpfile));
3708 terminx 190
 
4491 helixhorne 191
        fg->name = Xstrdup(internalgrpfiles[i].name);
3708 terminx 192
        fg->crcval = internalgrpfiles[i].crcval;
193
        fg->size = internalgrpfiles[i].size;
194
        fg->game = internalgrpfiles[i].game;
195
        fg->dependency = internalgrpfiles[i].dependency;
196
 
197
        if (internalgrpfiles[i].scriptname)
198
            fg->scriptname = dup_filename(internalgrpfiles[i].scriptname);
199
 
200
        if (internalgrpfiles[i].defname)
201
            fg->defname = dup_filename(internalgrpfiles[i].defname);
202
 
203
        fg->next = listgrps;
204
        listgrps = fg;
205
    }
206
 
207
    srch = klistpath("/", "*.grpinfo", CACHE1D_FIND_FILE);
208
 
209
    for (sidx = srch; sidx; sidx = sidx->next)
210
        LoadList(srch->name);
211
 
212
    klistfree(srch);
213
}
214
 
215
static void FreeGameList(void)
216
{
217
    struct grpfile *fg;
218
 
219
    while (listgrps)
220
    {
221
        fg = listgrps->next;
222
        Bfree(listgrps->name);
223
 
224
        if (listgrps->scriptname)
225
            Bfree(listgrps->scriptname);
226
 
227
        if (listgrps->defname)
228
            Bfree(listgrps->defname);
229
 
230
        Bfree(listgrps);
231
        listgrps = fg;
232
    }
233
}
234
 
235
 
241 terminx 236
#define GRPCACHEFILE "grpfiles.cache"
335 terminx 237
static struct grpcache
238
{
241 terminx 239
    struct grpcache *next;
1205 terminx 240
    int32_t size;
241
    int32_t mtime;
242
    int32_t crcval;
1457 terminx 243
    char name[BMAX_PATH];
335 terminx 244
}
245
*grpcache = NULL, *usedgrpcache = NULL;
241 terminx 246
 
1205 terminx 247
static int32_t LoadGroupsCache(void)
241 terminx 248
{
249
    struct grpcache *fg;
250
 
1205 terminx 251
    int32_t fsize, fmtime, fcrcval;
241 terminx 252
    char *fname;
253
 
254
    scriptfile *script;
255
 
256
    script = scriptfile_fromfile(GRPCACHEFILE);
257
    if (!script) return -1;
258
 
335 terminx 259
    while (!scriptfile_eof(script))
260
    {
2726 hendricks2 261
        if (scriptfile_getstring(script, &fname)) break;    // filename
262
        if (scriptfile_getnumber(script, &fsize)) break;    // filesize
263
        if (scriptfile_getnumber(script, &fmtime)) break;   // modification time
264
        if (scriptfile_getnumber(script, &fcrcval)) break;  // crc checksum
241 terminx 265
 
4491 helixhorne 266
        fg = (struct grpcache *)Xcalloc(1, sizeof(struct grpcache));
241 terminx 267
        fg->next = grpcache;
268
        grpcache = fg;
269
 
1221 terminx 270
        Bstrncpy(fg->name, fname, BMAX_PATH);
241 terminx 271
        fg->size = fsize;
272
        fg->mtime = fmtime;
273
        fg->crcval = fcrcval;
274
    }
275
 
276
    scriptfile_close(script);
277
    return 0;
278
}
279
 
280
static void FreeGroupsCache(void)
281
{
282
    struct grpcache *fg;
283
 
335 terminx 284
    while (grpcache)
285
    {
241 terminx 286
        fg = grpcache->next;
1527 terminx 287
        Bfree(grpcache);
241 terminx 288
        grpcache = fg;
289
    }
290
}
291
 
3654 terminx 292
void RemoveGroup(int32_t crcval)
293
{
3661 terminx 294
    struct grpfile *grp;
3654 terminx 295
 
296
    for (grp = foundgrps; grp; grp=grp->next)
297
    {
298
        if (grp->crcval == crcval)
299
        {
300
            if (grp == foundgrps)
301
                foundgrps = grp->next;
3661 terminx 302
            else
303
            {
304
                struct grpfile *fg;
3654 terminx 305
 
3661 terminx 306
                for (fg = foundgrps; fg; fg=fg->next)
307
                {
308
                    if (fg->next == grp)
309
                    {
310
                        fg->next = grp->next;
311
                        break;
312
                    }
313
                }
314
            }
315
 
3654 terminx 316
            Bfree((char *)grp->name);
317
            Bfree(grp);
318
 
3661 terminx 319
            RemoveGroup(crcval);
320
 
3654 terminx 321
            break;
322
        }
323
    }
324
}
325
 
326
struct grpfile * FindGroup(int32_t crcval)
327
{
328
    struct grpfile *grp;
329
 
330
    for (grp = foundgrps; grp; grp=grp->next)
331
    {
332
        if (grp->crcval == crcval)
333
            return grp;
334
    }
335
 
336
    return NULL;
337
}
338
 
1205 terminx 339
int32_t ScanGroups(void)
241 terminx 340
{
341
    CACHE1D_FIND_REC *srch, *sidx;
342
    struct grpcache *fg, *fgg;
343
    struct grpfile *grp;
344
    char *fn;
345
    struct Bstat st;
1430 terminx 346
#define BUFFER_SIZE (1024 * 1024 * 8)
4491 helixhorne 347
    uint8_t *buf = (uint8_t *)Xmalloc(BUFFER_SIZE);
241 terminx 348
 
1643 terminx 349
    initprintf("Searching for game data...\n");
241 terminx 350
 
3708 terminx 351
    LoadGameList();
241 terminx 352
    LoadGroupsCache();
353
 
354
    srch = klistpath("/", "*.grp", CACHE1D_FIND_FILE);
355
 
335 terminx 356
    for (sidx = srch; sidx; sidx = sidx->next)
357
    {
358
        for (fg = grpcache; fg; fg = fg->next)
359
        {
241 terminx 360
            if (!Bstrcmp(fg->name, sidx->name)) break;
361
        }
362
 
335 terminx 363
        if (fg)
364
        {
2726 hendricks2 365
            if (findfrompath(sidx->name, &fn)) continue; // failed to resolve the filename
335 terminx 366
            if (Bstat(fn, &st))
367
            {
1527 terminx 368
                Bfree(fn);
335 terminx 369
                continue;
2726 hendricks2 370
            } // failed to stat the file
1527 terminx 371
            Bfree(fn);
4997 terminx 372
            if (fg->size == (int32_t)st.st_size && fg->mtime == (int32_t)st.st_mtime)
335 terminx 373
            {
4491 helixhorne 374
                grp = (struct grpfile *)Xcalloc(1, sizeof(struct grpfile));
375
                grp->name = Xstrdup(sidx->name);
241 terminx 376
                grp->crcval = fg->crcval;
377
                grp->size = fg->size;
378
                grp->next = foundgrps;
379
                foundgrps = grp;
380
 
4491 helixhorne 381
                fgg = (struct grpcache *)Xcalloc(1, sizeof(struct grpcache));
241 terminx 382
                strcpy(fgg->name, fg->name);
383
                fgg->size = fg->size;
384
                fgg->mtime = fg->mtime;
385
                fgg->crcval = fg->crcval;
386
                fgg->next = usedgrpcache;
387
                usedgrpcache = fgg;
388
                continue;
389
            }
390
        }
391
 
392
        {
1205 terminx 393
            int32_t b, fh;
4625 terminx 394
            int32_t crcval = 0;
241 terminx 395
 
396
            fh = openfrompath(sidx->name, BO_RDONLY|BO_BINARY, BS_IREAD);
397
            if (fh < 0) continue;
3171 helixhorne 398
            if (Bfstat(fh, &st)) continue;
241 terminx 399
 
400
            initprintf(" Checksumming %s...", sidx->name);
335 terminx 401
            do
402
            {
1430 terminx 403
                b = read(fh, buf, BUFFER_SIZE);
4642 terminx 404
                if (b > 0) crcval = Bcrc32((uint8_t *)buf, b, crcval);
335 terminx 405
            }
1430 terminx 406
            while (b == BUFFER_SIZE);
241 terminx 407
            close(fh);
408
            initprintf(" Done\n");
409
 
4491 helixhorne 410
            grp = (struct grpfile *)Xcalloc(1, sizeof(struct grpfile));
411
            grp->name = Xstrdup(sidx->name);
241 terminx 412
            grp->crcval = crcval;
413
            grp->size = st.st_size;
414
            grp->next = foundgrps;
415
            foundgrps = grp;
416
 
4491 helixhorne 417
            fgg = (struct grpcache *)Xcalloc(1, sizeof(struct grpcache));
1221 terminx 418
            Bstrncpy(fgg->name, sidx->name, BMAX_PATH);
241 terminx 419
            fgg->size = st.st_size;
420
            fgg->mtime = st.st_mtime;
421
            fgg->crcval = crcval;
422
            fgg->next = usedgrpcache;
423
            usedgrpcache = fgg;
424
        }
425
    }
426
 
427
    klistfree(srch);
428
    FreeGroupsCache();
429
 
3654 terminx 430
    for (grp = foundgrps; grp; /*grp=grp->next*/)
431
    {
3708 terminx 432
        struct grpfile *igrp;
433
        for (igrp = listgrps; igrp; igrp=igrp->next)
434
            if (grp->crcval == igrp->crcval) break;
3654 terminx 435
 
3708 terminx 436
        if (igrp == NULL)
437
        {
438
            grp = grp->next;
439
            continue;
440
        }
3654 terminx 441
 
3708 terminx 442
        if (igrp->dependency)
3654 terminx 443
        {
3723 terminx 444
            struct grpfile *depgrp;
445
 
3654 terminx 446
            //initprintf("found grp with dep\n");
3723 terminx 447
            for (depgrp = foundgrps; depgrp; depgrp=depgrp->next)
448
                if (depgrp->crcval == igrp->dependency) break;
3654 terminx 449
 
3723 terminx 450
            if (depgrp == NULL || depgrp->crcval != igrp->dependency) // couldn't find dependency
3654 terminx 451
            {
452
                //initprintf("removing %s\n", grp->name);
3708 terminx 453
                RemoveGroup(igrp->crcval);
3654 terminx 454
                grp = foundgrps;
455
                continue;
456
            }
457
        }
458
 
3803 terminx 459
        if (igrp->game && !grp->game)
460
            grp->game = igrp->game;
461
 
3654 terminx 462
        grp=grp->next;
463
    }
464
 
335 terminx 465
    if (usedgrpcache)
466
    {
1205 terminx 467
        int32_t i = 0;
241 terminx 468
        FILE *fp;
469
        fp = fopen(GRPCACHEFILE, "wt");
335 terminx 470
        if (fp)
471
        {
472
            for (fg = usedgrpcache; fg; fg=fgg)
473
            {
241 terminx 474
                fgg = fg->next;
475
                fprintf(fp, "\"%s\" %d %d %d\n", fg->name, fg->size, fg->mtime, fg->crcval);
1527 terminx 476
                Bfree(fg);
1000 terminx 477
                i++;
241 terminx 478
            }
479
            fclose(fp);
480
        }
1178 terminx 481
//        initprintf("Found %d recognized GRP %s.\n",i,i>1?"files":"file");
2978 helixhorne 482
 
483
        Bfree(buf);
1000 terminx 484
        return 0;
241 terminx 485
    }
1642 terminx 486
 
487
    initprintf("Found no recognized game data!\n");
488
 
2978 helixhorne 489
    Bfree(buf);
241 terminx 490
    return 0;
491
}
492
 
3654 terminx 493
 
241 terminx 494
void FreeGroups(void)
495
{
496
    struct grpfile *fg;
497
 
335 terminx 498
    while (foundgrps)
499
    {
241 terminx 500
        fg = foundgrps->next;
1677 terminx 501
        Bfree((char *)foundgrps->name);
1527 terminx 502
        Bfree(foundgrps);
241 terminx 503
        foundgrps = fg;
504
    }
3708 terminx 505
 
506
    FreeGameList();
241 terminx 507
}
508