Subversion Repositories eduke32

Rev

Rev 4887 | Rev 5050 | 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);
71
    scriptfile_addsymbolvalue("DUKE15_CRC", DUKE15_CRC);
72
    scriptfile_addsymbolvalue("DUKE13_CRC", DUKE13_CRC);
73
    scriptfile_addsymbolvalue("DUKEDC_CRC", DUKEDC_CRC);
74
    scriptfile_addsymbolvalue("DUKECB_CRC", DUKECB_CRC);
75
    scriptfile_addsymbolvalue("DUKENW_CRC", DUKENW_CRC);
76
 
3711 helixhorne 77
    while (!scriptfile_eof(script))
3708 terminx 78
    {
3711 helixhorne 79
        enum
80
        {
81
            T_GRPINFO,
82
            T_GAMENAME,
83
            T_CRC,
84
            T_SIZE,
85
            T_DEPCRC,
86
            T_SCRIPTNAME,
87
            T_DEFNAME,
88
            T_FLAGS,
89
        };
3708 terminx 90
 
3711 helixhorne 91
        static const tokenlist profiletokens[] =
92
        {
93
            { "grpinfo",            T_GRPINFO },
94
        };
3708 terminx 95
 
4385 terminx 96
        int32_t token = getatoken(script,profiletokens,ARRAY_SIZE(profiletokens));
3708 terminx 97
        switch (token)
98
        {
99
        case T_GRPINFO:
3711 helixhorne 100
        {
101
            int32_t gsize = 0, gcrcval = 0, gflags = GAMEFLAG_DUKE, gdepcrc = DUKE15_CRC;
102
            char *gname = NULL, *gscript = NULL, *gdef = NULL;
103
 
104
            static const tokenlist grpinfotokens[] =
3708 terminx 105
            {
3711 helixhorne 106
                { "name",           T_GAMENAME },
107
                { "scriptname",     T_SCRIPTNAME },
108
                { "defname",        T_DEFNAME },
109
                { "crc",            T_CRC },
110
                { "dependency",     T_DEPCRC },
111
                { "size",           T_SIZE },
112
                { "flags",          T_FLAGS },
3708 terminx 113
 
3711 helixhorne 114
            };
3708 terminx 115
 
3711 helixhorne 116
            if (scriptfile_getbraces(script,&grpend)) break;
3708 terminx 117
 
3711 helixhorne 118
            while (script->textptr < grpend)
119
            {
4385 terminx 120
                int32_t token = getatoken(script,grpinfotokens,ARRAY_SIZE(grpinfotokens));
3708 terminx 121
 
3711 helixhorne 122
                switch (token)
3708 terminx 123
                {
3711 helixhorne 124
                case T_GAMENAME:
125
                    scriptfile_getstring(script,&gname); break;
126
                case T_SCRIPTNAME:
127
                    scriptfile_getstring(script,&gscript); break;
128
                case T_DEFNAME:
129
                    scriptfile_getstring(script,&gdef); break;
3708 terminx 130
 
3711 helixhorne 131
                case T_FLAGS:
132
                    scriptfile_getsymbol(script,&gflags); break;
133
                case T_DEPCRC:
134
                    scriptfile_getsymbol(script,&gdepcrc); break;
135
                case T_CRC:
136
                    scriptfile_getsymbol(script,&gcrcval); break;
137
                case T_SIZE:
138
                    scriptfile_getnumber(script,&gsize); break;
139
                default:
140
                    break;
141
                }
3708 terminx 142
 
4491 helixhorne 143
                fg = (struct grpfile *)Xcalloc(1, sizeof(struct grpfile));
3711 helixhorne 144
                fg->next = listgrps;
145
                listgrps = fg;
3708 terminx 146
 
3711 helixhorne 147
                if (gname)
4491 helixhorne 148
                    fg->name = Xstrdup(gname);
3708 terminx 149
 
3711 helixhorne 150
                fg->size = gsize;
151
                fg->crcval = gcrcval;
152
                fg->dependency = gdepcrc;
153
                fg->game = gflags;
3708 terminx 154
 
3711 helixhorne 155
                if (gscript)
156
                    fg->scriptname = dup_filename(gscript);
3708 terminx 157
 
3711 helixhorne 158
                if (gdef)
159
                    fg->defname = dup_filename(gdef);
3708 terminx 160
            }
3711 helixhorne 161
            break;
162
        }
3708 terminx 163
 
164
        default:
165
            break;
166
        }
167
    }
168
 
169
    scriptfile_close(script);
170
    scriptfile_clearsymbols();
171
}
172
 
173
static void LoadGameList(void)
174
{
175
    struct grpfile *fg;
176
    CACHE1D_FIND_REC *srch, *sidx;
177
 
178
    int32_t i;
179
 
180
    for (i = 0; i<NUMGRPFILES; i++)
181
    {
4491 helixhorne 182
        fg = (struct grpfile *)Xcalloc(1, sizeof(struct grpfile));
3708 terminx 183
 
4491 helixhorne 184
        fg->name = Xstrdup(internalgrpfiles[i].name);
3708 terminx 185
        fg->crcval = internalgrpfiles[i].crcval;
186
        fg->size = internalgrpfiles[i].size;
187
        fg->game = internalgrpfiles[i].game;
188
        fg->dependency = internalgrpfiles[i].dependency;
189
 
190
        if (internalgrpfiles[i].scriptname)
191
            fg->scriptname = dup_filename(internalgrpfiles[i].scriptname);
192
 
193
        if (internalgrpfiles[i].defname)
194
            fg->defname = dup_filename(internalgrpfiles[i].defname);
195
 
196
        fg->next = listgrps;
197
        listgrps = fg;
198
    }
199
 
200
    srch = klistpath("/", "*.grpinfo", CACHE1D_FIND_FILE);
201
 
202
    for (sidx = srch; sidx; sidx = sidx->next)
203
        LoadList(srch->name);
204
 
205
    klistfree(srch);
206
}
207
 
208
static void FreeGameList(void)
209
{
210
    struct grpfile *fg;
211
 
212
    while (listgrps)
213
    {
214
        fg = listgrps->next;
215
        Bfree(listgrps->name);
216
 
217
        if (listgrps->scriptname)
218
            Bfree(listgrps->scriptname);
219
 
220
        if (listgrps->defname)
221
            Bfree(listgrps->defname);
222
 
223
        Bfree(listgrps);
224
        listgrps = fg;
225
    }
226
}
227
 
228
 
241 terminx 229
#define GRPCACHEFILE "grpfiles.cache"
335 terminx 230
static struct grpcache
231
{
241 terminx 232
    struct grpcache *next;
1205 terminx 233
    int32_t size;
234
    int32_t mtime;
235
    int32_t crcval;
1457 terminx 236
    char name[BMAX_PATH];
335 terminx 237
}
238
*grpcache = NULL, *usedgrpcache = NULL;
241 terminx 239
 
1205 terminx 240
static int32_t LoadGroupsCache(void)
241 terminx 241
{
242
    struct grpcache *fg;
243
 
1205 terminx 244
    int32_t fsize, fmtime, fcrcval;
241 terminx 245
    char *fname;
246
 
247
    scriptfile *script;
248
 
249
    script = scriptfile_fromfile(GRPCACHEFILE);
250
    if (!script) return -1;
251
 
335 terminx 252
    while (!scriptfile_eof(script))
253
    {
2726 hendricks2 254
        if (scriptfile_getstring(script, &fname)) break;    // filename
255
        if (scriptfile_getnumber(script, &fsize)) break;    // filesize
256
        if (scriptfile_getnumber(script, &fmtime)) break;   // modification time
257
        if (scriptfile_getnumber(script, &fcrcval)) break;  // crc checksum
241 terminx 258
 
4491 helixhorne 259
        fg = (struct grpcache *)Xcalloc(1, sizeof(struct grpcache));
241 terminx 260
        fg->next = grpcache;
261
        grpcache = fg;
262
 
1221 terminx 263
        Bstrncpy(fg->name, fname, BMAX_PATH);
241 terminx 264
        fg->size = fsize;
265
        fg->mtime = fmtime;
266
        fg->crcval = fcrcval;
267
    }
268
 
269
    scriptfile_close(script);
270
    return 0;
271
}
272
 
273
static void FreeGroupsCache(void)
274
{
275
    struct grpcache *fg;
276
 
335 terminx 277
    while (grpcache)
278
    {
241 terminx 279
        fg = grpcache->next;
1527 terminx 280
        Bfree(grpcache);
241 terminx 281
        grpcache = fg;
282
    }
283
}
284
 
3654 terminx 285
void RemoveGroup(int32_t crcval)
286
{
3661 terminx 287
    struct grpfile *grp;
3654 terminx 288
 
289
    for (grp = foundgrps; grp; grp=grp->next)
290
    {
291
        if (grp->crcval == crcval)
292
        {
293
            if (grp == foundgrps)
294
                foundgrps = grp->next;
3661 terminx 295
            else
296
            {
297
                struct grpfile *fg;
3654 terminx 298
 
3661 terminx 299
                for (fg = foundgrps; fg; fg=fg->next)
300
                {
301
                    if (fg->next == grp)
302
                    {
303
                        fg->next = grp->next;
304
                        break;
305
                    }
306
                }
307
            }
308
 
3654 terminx 309
            Bfree((char *)grp->name);
310
            Bfree(grp);
311
 
3661 terminx 312
            RemoveGroup(crcval);
313
 
3654 terminx 314
            break;
315
        }
316
    }
317
}
318
 
319
struct grpfile * FindGroup(int32_t crcval)
320
{
321
    struct grpfile *grp;
322
 
323
    for (grp = foundgrps; grp; grp=grp->next)
324
    {
325
        if (grp->crcval == crcval)
326
            return grp;
327
    }
328
 
329
    return NULL;
330
}
331
 
1205 terminx 332
int32_t ScanGroups(void)
241 terminx 333
{
334
    CACHE1D_FIND_REC *srch, *sidx;
335
    struct grpcache *fg, *fgg;
336
    struct grpfile *grp;
337
    char *fn;
338
    struct Bstat st;
1430 terminx 339
#define BUFFER_SIZE (1024 * 1024 * 8)
4491 helixhorne 340
    uint8_t *buf = (uint8_t *)Xmalloc(BUFFER_SIZE);
241 terminx 341
 
1643 terminx 342
    initprintf("Searching for game data...\n");
241 terminx 343
 
3708 terminx 344
    LoadGameList();
241 terminx 345
    LoadGroupsCache();
346
 
347
    srch = klistpath("/", "*.grp", CACHE1D_FIND_FILE);
348
 
335 terminx 349
    for (sidx = srch; sidx; sidx = sidx->next)
350
    {
351
        for (fg = grpcache; fg; fg = fg->next)
352
        {
241 terminx 353
            if (!Bstrcmp(fg->name, sidx->name)) break;
354
        }
355
 
335 terminx 356
        if (fg)
357
        {
2726 hendricks2 358
            if (findfrompath(sidx->name, &fn)) continue; // failed to resolve the filename
335 terminx 359
            if (Bstat(fn, &st))
360
            {
1527 terminx 361
                Bfree(fn);
335 terminx 362
                continue;
2726 hendricks2 363
            } // failed to stat the file
1527 terminx 364
            Bfree(fn);
4997 terminx 365
            if (fg->size == (int32_t)st.st_size && fg->mtime == (int32_t)st.st_mtime)
335 terminx 366
            {
4491 helixhorne 367
                grp = (struct grpfile *)Xcalloc(1, sizeof(struct grpfile));
368
                grp->name = Xstrdup(sidx->name);
241 terminx 369
                grp->crcval = fg->crcval;
370
                grp->size = fg->size;
371
                grp->next = foundgrps;
372
                foundgrps = grp;
373
 
4491 helixhorne 374
                fgg = (struct grpcache *)Xcalloc(1, sizeof(struct grpcache));
241 terminx 375
                strcpy(fgg->name, fg->name);
376
                fgg->size = fg->size;
377
                fgg->mtime = fg->mtime;
378
                fgg->crcval = fg->crcval;
379
                fgg->next = usedgrpcache;
380
                usedgrpcache = fgg;
381
                continue;
382
            }
383
        }
384
 
385
        {
1205 terminx 386
            int32_t b, fh;
4625 terminx 387
            int32_t crcval = 0;
241 terminx 388
 
389
            fh = openfrompath(sidx->name, BO_RDONLY|BO_BINARY, BS_IREAD);
390
            if (fh < 0) continue;
3171 helixhorne 391
            if (Bfstat(fh, &st)) continue;
241 terminx 392
 
393
            initprintf(" Checksumming %s...", sidx->name);
335 terminx 394
            do
395
            {
1430 terminx 396
                b = read(fh, buf, BUFFER_SIZE);
4642 terminx 397
                if (b > 0) crcval = Bcrc32((uint8_t *)buf, b, crcval);
335 terminx 398
            }
1430 terminx 399
            while (b == BUFFER_SIZE);
241 terminx 400
            close(fh);
401
            initprintf(" Done\n");
402
 
4491 helixhorne 403
            grp = (struct grpfile *)Xcalloc(1, sizeof(struct grpfile));
404
            grp->name = Xstrdup(sidx->name);
241 terminx 405
            grp->crcval = crcval;
406
            grp->size = st.st_size;
407
            grp->next = foundgrps;
408
            foundgrps = grp;
409
 
4491 helixhorne 410
            fgg = (struct grpcache *)Xcalloc(1, sizeof(struct grpcache));
1221 terminx 411
            Bstrncpy(fgg->name, sidx->name, BMAX_PATH);
241 terminx 412
            fgg->size = st.st_size;
413
            fgg->mtime = st.st_mtime;
414
            fgg->crcval = crcval;
415
            fgg->next = usedgrpcache;
416
            usedgrpcache = fgg;
417
        }
418
    }
419
 
420
    klistfree(srch);
421
    FreeGroupsCache();
422
 
3654 terminx 423
    for (grp = foundgrps; grp; /*grp=grp->next*/)
424
    {
3708 terminx 425
        struct grpfile *igrp;
426
        for (igrp = listgrps; igrp; igrp=igrp->next)
427
            if (grp->crcval == igrp->crcval) break;
3654 terminx 428
 
3708 terminx 429
        if (igrp == NULL)
430
        {
431
            grp = grp->next;
432
            continue;
433
        }
3654 terminx 434
 
3708 terminx 435
        if (igrp->dependency)
3654 terminx 436
        {
3723 terminx 437
            struct grpfile *depgrp;
438
 
3654 terminx 439
            //initprintf("found grp with dep\n");
3723 terminx 440
            for (depgrp = foundgrps; depgrp; depgrp=depgrp->next)
441
                if (depgrp->crcval == igrp->dependency) break;
3654 terminx 442
 
3723 terminx 443
            if (depgrp == NULL || depgrp->crcval != igrp->dependency) // couldn't find dependency
3654 terminx 444
            {
445
                //initprintf("removing %s\n", grp->name);
3708 terminx 446
                RemoveGroup(igrp->crcval);
3654 terminx 447
                grp = foundgrps;
448
                continue;
449
            }
450
        }
451
 
3803 terminx 452
        if (igrp->game && !grp->game)
453
            grp->game = igrp->game;
454
 
3654 terminx 455
        grp=grp->next;
456
    }
457
 
335 terminx 458
    if (usedgrpcache)
459
    {
1205 terminx 460
        int32_t i = 0;
241 terminx 461
        FILE *fp;
462
        fp = fopen(GRPCACHEFILE, "wt");
335 terminx 463
        if (fp)
464
        {
465
            for (fg = usedgrpcache; fg; fg=fgg)
466
            {
241 terminx 467
                fgg = fg->next;
468
                fprintf(fp, "\"%s\" %d %d %d\n", fg->name, fg->size, fg->mtime, fg->crcval);
1527 terminx 469
                Bfree(fg);
1000 terminx 470
                i++;
241 terminx 471
            }
472
            fclose(fp);
473
        }
1178 terminx 474
//        initprintf("Found %d recognized GRP %s.\n",i,i>1?"files":"file");
2978 helixhorne 475
 
476
        Bfree(buf);
1000 terminx 477
        return 0;
241 terminx 478
    }
1642 terminx 479
 
480
    initprintf("Found no recognized game data!\n");
481
 
2978 helixhorne 482
    Bfree(buf);
241 terminx 483
    return 0;
484
}
485
 
3654 terminx 486
 
241 terminx 487
void FreeGroups(void)
488
{
489
    struct grpfile *fg;
490
 
335 terminx 491
    while (foundgrps)
492
    {
241 terminx 493
        fg = foundgrps->next;
1677 terminx 494
        Bfree((char *)foundgrps->name);
1527 terminx 495
        Bfree(foundgrps);
241 terminx 496
        foundgrps = fg;
497
    }
3708 terminx 498
 
499
    FreeGameList();
241 terminx 500
}
501